Merge from rustc
This commit is contained in:
commit
d49845e5fe
922 changed files with 22138 additions and 8888 deletions
5
.github/workflows/ci.yml
vendored
5
.github/workflows/ci.yml
vendored
|
|
@ -235,8 +235,9 @@ jobs:
|
|||
DATADOG_API_KEY: ${{ secrets.DATADOG_API_KEY }}
|
||||
DD_GITHUB_JOB_NAME: ${{ matrix.name }}
|
||||
run: |
|
||||
npm install -g @datadog/datadog-ci@^2.x.x
|
||||
python3 src/ci/scripts/upload-build-metrics.py build/cpu-usage.csv
|
||||
cd src/ci
|
||||
npm ci
|
||||
python3 scripts/upload-build-metrics.py ../../build/cpu-usage.csv
|
||||
|
||||
# This job isused to tell bors the final status of the build, as there is no practical way to detect
|
||||
# when a workflow is successful listening to webhooks only in our current bors implementation (homu).
|
||||
|
|
|
|||
64
Cargo.lock
64
Cargo.lock
|
|
@ -3354,7 +3354,7 @@ dependencies = [
|
|||
"itertools",
|
||||
"rustc_ast",
|
||||
"rustc_ast_pretty",
|
||||
"rustc_attr",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_feature",
|
||||
|
|
@ -3380,7 +3380,7 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_attr"
|
||||
name = "rustc_attr_data_structures"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rustc_abi",
|
||||
|
|
@ -3397,6 +3397,25 @@ dependencies = [
|
|||
"rustc_span",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_attr_parsing"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rustc_abi",
|
||||
"rustc_ast",
|
||||
"rustc_ast_pretty",
|
||||
"rustc_attr_data_structures",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_feature",
|
||||
"rustc_fluent_macro",
|
||||
"rustc_lexer",
|
||||
"rustc_macros",
|
||||
"rustc_serialize",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_baked_icu_data"
|
||||
version = "0.0.0"
|
||||
|
|
@ -3441,7 +3460,7 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"rustc_ast",
|
||||
"rustc_ast_pretty",
|
||||
"rustc_attr",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_expand",
|
||||
|
|
@ -3473,7 +3492,7 @@ dependencies = [
|
|||
"rustc-demangle",
|
||||
"rustc_abi",
|
||||
"rustc_ast",
|
||||
"rustc_attr",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_codegen_ssa",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
|
|
@ -3515,12 +3534,13 @@ dependencies = [
|
|||
"rustc_arena",
|
||||
"rustc_ast",
|
||||
"rustc_ast_pretty",
|
||||
"rustc_attr",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_fluent_macro",
|
||||
"rustc_fs_util",
|
||||
"rustc_hir",
|
||||
"rustc_hir_pretty",
|
||||
"rustc_incremental",
|
||||
"rustc_index",
|
||||
"rustc_macros",
|
||||
|
|
@ -3552,7 +3572,7 @@ dependencies = [
|
|||
"rustc_abi",
|
||||
"rustc_apfloat",
|
||||
"rustc_ast",
|
||||
"rustc_attr",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_fluent_macro",
|
||||
|
|
@ -3619,7 +3639,7 @@ dependencies = [
|
|||
"rustc_ast_lowering",
|
||||
"rustc_ast_passes",
|
||||
"rustc_ast_pretty",
|
||||
"rustc_attr",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_borrowck",
|
||||
"rustc_builtin_macros",
|
||||
"rustc_codegen_ssa",
|
||||
|
|
@ -3723,7 +3743,7 @@ dependencies = [
|
|||
"rustc_ast",
|
||||
"rustc_ast_passes",
|
||||
"rustc_ast_pretty",
|
||||
"rustc_attr",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_feature",
|
||||
|
|
@ -3786,6 +3806,7 @@ dependencies = [
|
|||
"rustc_span",
|
||||
"rustc_target",
|
||||
"smallvec",
|
||||
"thin-vec",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
|
|
@ -3797,7 +3818,7 @@ dependencies = [
|
|||
"rustc_abi",
|
||||
"rustc_arena",
|
||||
"rustc_ast",
|
||||
"rustc_attr",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_feature",
|
||||
|
|
@ -3836,7 +3857,7 @@ dependencies = [
|
|||
"rustc_abi",
|
||||
"rustc_ast",
|
||||
"rustc_ast_ir",
|
||||
"rustc_attr",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_fluent_macro",
|
||||
|
|
@ -3925,7 +3946,7 @@ dependencies = [
|
|||
"rustc_ast_lowering",
|
||||
"rustc_ast_passes",
|
||||
"rustc_ast_pretty",
|
||||
"rustc_attr",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_borrowck",
|
||||
"rustc_builtin_macros",
|
||||
"rustc_codegen_llvm",
|
||||
|
|
@ -3981,7 +4002,7 @@ dependencies = [
|
|||
"rustc_abi",
|
||||
"rustc_ast",
|
||||
"rustc_ast_pretty",
|
||||
"rustc_attr",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_feature",
|
||||
|
|
@ -4055,7 +4076,7 @@ dependencies = [
|
|||
"odht",
|
||||
"rustc_abi",
|
||||
"rustc_ast",
|
||||
"rustc_attr",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_expand",
|
||||
|
|
@ -4092,7 +4113,7 @@ dependencies = [
|
|||
"rustc_arena",
|
||||
"rustc_ast",
|
||||
"rustc_ast_ir",
|
||||
"rustc_attr",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_data_structures",
|
||||
"rustc_error_messages",
|
||||
"rustc_errors",
|
||||
|
|
@ -4171,7 +4192,7 @@ dependencies = [
|
|||
"rustc_abi",
|
||||
"rustc_arena",
|
||||
"rustc_ast",
|
||||
"rustc_attr",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_const_eval",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
|
|
@ -4197,7 +4218,7 @@ name = "rustc_monomorphize"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rustc_abi",
|
||||
"rustc_attr",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_fluent_macro",
|
||||
|
|
@ -4265,7 +4286,7 @@ dependencies = [
|
|||
"rustc_abi",
|
||||
"rustc_ast",
|
||||
"rustc_ast_pretty",
|
||||
"rustc_attr",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_expand",
|
||||
|
|
@ -4273,7 +4294,6 @@ dependencies = [
|
|||
"rustc_fluent_macro",
|
||||
"rustc_hir",
|
||||
"rustc_index",
|
||||
"rustc_lexer",
|
||||
"rustc_macros",
|
||||
"rustc_middle",
|
||||
"rustc_privacy",
|
||||
|
|
@ -4312,7 +4332,7 @@ name = "rustc_privacy"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rustc_ast",
|
||||
"rustc_attr",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_fluent_macro",
|
||||
|
|
@ -4376,7 +4396,7 @@ dependencies = [
|
|||
"rustc_arena",
|
||||
"rustc_ast",
|
||||
"rustc_ast_pretty",
|
||||
"rustc_attr",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_expand",
|
||||
|
|
@ -4454,9 +4474,9 @@ version = "0.0.0"
|
|||
dependencies = [
|
||||
"rustc_abi",
|
||||
"rustc_ast",
|
||||
"rustc_ast_pretty",
|
||||
"rustc_data_structures",
|
||||
"rustc_hir",
|
||||
"rustc_hir_pretty",
|
||||
"rustc_middle",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
|
|
@ -4533,7 +4553,7 @@ dependencies = [
|
|||
"rustc_abi",
|
||||
"rustc_ast",
|
||||
"rustc_ast_ir",
|
||||
"rustc_attr",
|
||||
"rustc_attr_parsing",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_fluent_macro",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
use std::fmt;
|
||||
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
//! - [`UnOp`], [`BinOp`], and [`BinOpKind`]: Unary and binary operators.
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::{cmp, fmt, mem};
|
||||
use std::{cmp, fmt};
|
||||
|
||||
pub use GenericArgs::*;
|
||||
pub use UnsafeSource::*;
|
||||
|
|
@ -31,8 +31,7 @@ use rustc_data_structures::sync::Lrc;
|
|||
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
|
||||
pub use rustc_span::AttrId;
|
||||
use rustc_span::source_map::{Spanned, respan};
|
||||
use rustc_span::symbol::{Ident, Symbol, kw, sym};
|
||||
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
|
||||
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
|
||||
pub use crate::format::*;
|
||||
|
|
@ -859,6 +858,8 @@ pub enum PatKind {
|
|||
pub enum PatFieldsRest {
|
||||
/// `module::StructName { field, ..}`
|
||||
Rest,
|
||||
/// `module::StructName { field, syntax error }`
|
||||
Recovered(ErrorGuaranteed),
|
||||
/// `module::StructName { field }`
|
||||
None,
|
||||
}
|
||||
|
|
@ -1758,53 +1759,16 @@ pub enum AttrArgs {
|
|||
Eq {
|
||||
/// Span of the `=` token.
|
||||
eq_span: Span,
|
||||
|
||||
value: AttrArgsEq,
|
||||
expr: P<Expr>,
|
||||
},
|
||||
}
|
||||
|
||||
// The RHS of an `AttrArgs::Eq` starts out as an expression. Once macro
|
||||
// expansion is completed, all cases end up either as a meta item literal,
|
||||
// which is the form used after lowering to HIR, or as an error.
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub enum AttrArgsEq {
|
||||
Ast(P<Expr>),
|
||||
Hir(MetaItemLit),
|
||||
}
|
||||
|
||||
impl AttrArgsEq {
|
||||
pub fn span(&self) -> Span {
|
||||
match self {
|
||||
AttrArgsEq::Ast(p) => p.span,
|
||||
AttrArgsEq::Hir(lit) => lit.span,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unwrap_ast(&self) -> &Expr {
|
||||
match self {
|
||||
AttrArgsEq::Ast(p) => p,
|
||||
AttrArgsEq::Hir(lit) => {
|
||||
unreachable!("in literal form when getting inner tokens: {lit:?}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unwrap_ast_mut(&mut self) -> &mut P<Expr> {
|
||||
match self {
|
||||
AttrArgsEq::Ast(p) => p,
|
||||
AttrArgsEq::Hir(lit) => {
|
||||
unreachable!("in literal form when getting inner tokens: {lit:?}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AttrArgs {
|
||||
pub fn span(&self) -> Option<Span> {
|
||||
match self {
|
||||
AttrArgs::Empty => None,
|
||||
AttrArgs::Delimited(args) => Some(args.dspan.entire()),
|
||||
AttrArgs::Eq { eq_span, value } => Some(eq_span.to(value.span())),
|
||||
AttrArgs::Eq { eq_span, expr } => Some(eq_span.to(expr.span)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1814,27 +1778,7 @@ impl AttrArgs {
|
|||
match self {
|
||||
AttrArgs::Empty => TokenStream::default(),
|
||||
AttrArgs::Delimited(args) => args.tokens.clone(),
|
||||
AttrArgs::Eq { value, .. } => TokenStream::from_ast(value.unwrap_ast()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<CTX> HashStable<CTX> for AttrArgs
|
||||
where
|
||||
CTX: crate::HashStableContext,
|
||||
{
|
||||
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
|
||||
mem::discriminant(self).hash_stable(ctx, hasher);
|
||||
match self {
|
||||
AttrArgs::Empty => {}
|
||||
AttrArgs::Delimited(args) => args.hash_stable(ctx, hasher),
|
||||
AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => {
|
||||
unreachable!("hash_stable {:?}", expr);
|
||||
}
|
||||
AttrArgs::Eq { eq_span, value: AttrArgsEq::Hir(lit) } => {
|
||||
eq_span.hash_stable(ctx, hasher);
|
||||
lit.hash_stable(ctx, hasher);
|
||||
}
|
||||
AttrArgs::Eq { expr, .. } => TokenStream::from_ast(expr),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3051,7 +2995,7 @@ impl NormalAttr {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub struct AttrItem {
|
||||
pub unsafety: Safety,
|
||||
pub path: Path,
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
//! Functions dealing with attributes and meta items.
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::iter;
|
||||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
|
||||
use rustc_index::bit_set::GrowableBitSet;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::{Ident, Symbol, sym};
|
||||
use rustc_span::{Ident, Span, Symbol, sym};
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
|
||||
use crate::ast::{
|
||||
AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute, DUMMY_NODE_ID,
|
||||
DelimArgs, Expr, ExprKind, LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit,
|
||||
NormalAttr, Path, PathSegment, Safety,
|
||||
AttrArgs, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute, DUMMY_NODE_ID, DelimArgs,
|
||||
Expr, ExprKind, LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, NormalAttr, Path,
|
||||
PathSegment, Safety,
|
||||
};
|
||||
use crate::ptr::P;
|
||||
use crate::token::{self, CommentKind, Delimiter, Token};
|
||||
|
|
@ -66,11 +66,27 @@ impl Attribute {
|
|||
AttrKind::DocComment(..) => panic!("unexpected doc comment"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AttributeExt for Attribute {
|
||||
fn id(&self) -> AttrId {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn value_span(&self) -> Option<Span> {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => match &normal.item.args {
|
||||
AttrArgs::Eq { expr, .. } => Some(expr.span),
|
||||
_ => None,
|
||||
},
|
||||
AttrKind::DocComment(..) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if it is a sugared doc comment (`///` or `//!` for example).
|
||||
/// So `#[doc = "doc"]` (which is a doc comment) and `#[doc(...)]` (which is not
|
||||
/// a doc comment) will return `false`.
|
||||
pub fn is_doc_comment(&self) -> bool {
|
||||
fn is_doc_comment(&self) -> bool {
|
||||
match self.kind {
|
||||
AttrKind::Normal(..) => false,
|
||||
AttrKind::DocComment(..) => true,
|
||||
|
|
@ -78,7 +94,7 @@ impl Attribute {
|
|||
}
|
||||
|
||||
/// For a single-segment attribute, returns its name; otherwise, returns `None`.
|
||||
pub fn ident(&self) -> Option<Ident> {
|
||||
fn ident(&self) -> Option<Ident> {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => {
|
||||
if let [ident] = &*normal.item.path.segments {
|
||||
|
|
@ -91,28 +107,14 @@ impl Attribute {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn name_or_empty(&self) -> Symbol {
|
||||
self.ident().unwrap_or_else(Ident::empty).name
|
||||
}
|
||||
|
||||
pub fn path(&self) -> SmallVec<[Symbol; 1]> {
|
||||
fn ident_path(&self) -> Option<SmallVec<[Ident; 1]>> {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => {
|
||||
normal.item.path.segments.iter().map(|s| s.ident.name).collect()
|
||||
}
|
||||
AttrKind::DocComment(..) => smallvec![sym::doc],
|
||||
AttrKind::Normal(p) => Some(p.item.path.segments.iter().map(|i| i.ident).collect()),
|
||||
AttrKind::DocComment(_, _) => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn has_name(&self, name: Symbol) -> bool {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => normal.item.path == name,
|
||||
AttrKind::DocComment(..) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn path_matches(&self, name: &[Symbol]) -> bool {
|
||||
fn path_matches(&self, name: &[Symbol]) -> bool {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => {
|
||||
normal.item.path.segments.len() == name.len()
|
||||
|
|
@ -128,7 +130,11 @@ impl Attribute {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_word(&self) -> bool {
|
||||
fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
|
||||
fn is_word(&self) -> bool {
|
||||
if let AttrKind::Normal(normal) = &self.kind {
|
||||
matches!(normal.item.args, AttrArgs::Empty)
|
||||
} else {
|
||||
|
|
@ -143,7 +149,7 @@ impl Attribute {
|
|||
/// #[attr = ""] // Returns `None`.
|
||||
/// #[attr] // Returns `None`.
|
||||
/// ```
|
||||
pub fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> {
|
||||
fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => normal.item.meta_item_list(),
|
||||
AttrKind::DocComment(..) => None,
|
||||
|
|
@ -165,7 +171,7 @@ impl Attribute {
|
|||
/// ```text
|
||||
/// #[attr("value")]
|
||||
/// ```
|
||||
pub fn value_str(&self) -> Option<Symbol> {
|
||||
fn value_str(&self) -> Option<Symbol> {
|
||||
match &self.kind {
|
||||
AttrKind::Normal(normal) => normal.item.value_str(),
|
||||
AttrKind::DocComment(..) => None,
|
||||
|
|
@ -177,7 +183,7 @@ impl Attribute {
|
|||
/// * `/** doc */` returns `Some(("doc", CommentKind::Block))`.
|
||||
/// * `#[doc = "doc"]` returns `Some(("doc", CommentKind::Line))`.
|
||||
/// * `#[doc(...)]` returns `None`.
|
||||
pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
|
||||
fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
|
||||
match &self.kind {
|
||||
AttrKind::DocComment(kind, data) => Some((*data, *kind)),
|
||||
AttrKind::Normal(normal) if normal.item.path == sym::doc => {
|
||||
|
|
@ -191,7 +197,7 @@ impl Attribute {
|
|||
/// * `///doc` returns `Some("doc")`.
|
||||
/// * `#[doc = "doc"]` returns `Some("doc")`.
|
||||
/// * `#[doc(...)]` returns `None`.
|
||||
pub fn doc_str(&self) -> Option<Symbol> {
|
||||
fn doc_str(&self) -> Option<Symbol> {
|
||||
match &self.kind {
|
||||
AttrKind::DocComment(.., data) => Some(*data),
|
||||
AttrKind::Normal(normal) if normal.item.path == sym::doc => normal.item.value_str(),
|
||||
|
|
@ -199,16 +205,16 @@ impl Attribute {
|
|||
}
|
||||
}
|
||||
|
||||
fn style(&self) -> AttrStyle {
|
||||
self.style
|
||||
}
|
||||
}
|
||||
|
||||
impl Attribute {
|
||||
pub fn may_have_doc_links(&self) -> bool {
|
||||
self.doc_str().is_some_and(|s| comments::may_have_doc_links(s.as_str()))
|
||||
}
|
||||
|
||||
pub fn is_proc_macro_attr(&self) -> bool {
|
||||
[sym::proc_macro, sym::proc_macro_attribute, sym::proc_macro_derive]
|
||||
.iter()
|
||||
.any(|kind| self.has_name(*kind))
|
||||
}
|
||||
|
||||
/// Extracts the MetaItem from inside this Attribute.
|
||||
pub fn meta(&self) -> Option<MetaItem> {
|
||||
match &self.kind {
|
||||
|
|
@ -268,7 +274,12 @@ impl AttrItem {
|
|||
/// ```
|
||||
fn value_str(&self) -> Option<Symbol> {
|
||||
match &self.args {
|
||||
AttrArgs::Eq { value, .. } => value.value_str(),
|
||||
AttrArgs::Eq { expr, .. } => match expr.kind {
|
||||
ExprKind::Lit(token_lit) => {
|
||||
LitKind::from_token_lit(token_lit).ok().and_then(|lit| lit.str())
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
AttrArgs::Delimited(_) | AttrArgs::Empty => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -287,20 +298,6 @@ impl AttrItem {
|
|||
}
|
||||
}
|
||||
|
||||
impl AttrArgsEq {
|
||||
fn value_str(&self) -> Option<Symbol> {
|
||||
match self {
|
||||
AttrArgsEq::Ast(expr) => match expr.kind {
|
||||
ExprKind::Lit(token_lit) => {
|
||||
LitKind::from_token_lit(token_lit).ok().and_then(|lit| lit.str())
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
AttrArgsEq::Hir(lit) => lit.kind.str(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MetaItem {
|
||||
/// For a single-segment meta item, returns its name; otherwise, returns `None`.
|
||||
pub fn ident(&self) -> Option<Ident> {
|
||||
|
|
@ -439,7 +436,8 @@ impl MetaItem {
|
|||
}
|
||||
|
||||
impl MetaItemKind {
|
||||
fn list_from_tokens(tokens: TokenStream) -> Option<ThinVec<MetaItemInner>> {
|
||||
// public because it can be called in the hir
|
||||
pub fn list_from_tokens(tokens: TokenStream) -> Option<ThinVec<MetaItemInner>> {
|
||||
let mut tokens = tokens.trees().peekable();
|
||||
let mut result = ThinVec::new();
|
||||
while tokens.peek().is_some() {
|
||||
|
|
@ -492,7 +490,7 @@ impl MetaItemKind {
|
|||
MetaItemKind::list_from_tokens(tokens.clone()).map(MetaItemKind::List)
|
||||
}
|
||||
AttrArgs::Delimited(..) => None,
|
||||
AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => match expr.kind {
|
||||
AttrArgs::Eq { expr, .. } => match expr.kind {
|
||||
ExprKind::Lit(token_lit) => {
|
||||
// Turn failures to `None`, we'll get parse errors elsewhere.
|
||||
MetaItemLit::from_token_lit(token_lit, expr.span)
|
||||
|
|
@ -501,9 +499,6 @@ impl MetaItemKind {
|
|||
}
|
||||
_ => None,
|
||||
},
|
||||
AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => {
|
||||
Some(MetaItemKind::NameValue(lit.clone()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -704,26 +699,175 @@ pub fn mk_attr_name_value_str(
|
|||
tokens: None,
|
||||
});
|
||||
let path = Path::from_ident(Ident::new(name, span));
|
||||
let args = AttrArgs::Eq { eq_span: span, value: AttrArgsEq::Ast(expr) };
|
||||
let args = AttrArgs::Eq { eq_span: span, expr };
|
||||
mk_attr(g, style, unsafety, path, args, span)
|
||||
}
|
||||
|
||||
pub fn filter_by_name(attrs: &[Attribute], name: Symbol) -> impl Iterator<Item = &Attribute> {
|
||||
pub fn filter_by_name<A: AttributeExt>(attrs: &[A], name: Symbol) -> impl Iterator<Item = &A> {
|
||||
attrs.iter().filter(move |attr| attr.has_name(name))
|
||||
}
|
||||
|
||||
pub fn find_by_name(attrs: &[Attribute], name: Symbol) -> Option<&Attribute> {
|
||||
pub fn find_by_name<A: AttributeExt>(attrs: &[A], name: Symbol) -> Option<&A> {
|
||||
filter_by_name(attrs, name).next()
|
||||
}
|
||||
|
||||
pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: Symbol) -> Option<Symbol> {
|
||||
pub fn first_attr_value_str_by_name(attrs: &[impl AttributeExt], name: Symbol) -> Option<Symbol> {
|
||||
find_by_name(attrs, name).and_then(|attr| attr.value_str())
|
||||
}
|
||||
|
||||
pub fn contains_name(attrs: &[Attribute], name: Symbol) -> bool {
|
||||
pub fn contains_name(attrs: &[impl AttributeExt], name: Symbol) -> bool {
|
||||
find_by_name(attrs, name).is_some()
|
||||
}
|
||||
|
||||
pub fn list_contains_name(items: &[MetaItemInner], name: Symbol) -> bool {
|
||||
items.iter().any(|item| item.has_name(name))
|
||||
}
|
||||
|
||||
impl MetaItemLit {
|
||||
pub fn value_str(&self) -> Option<Symbol> {
|
||||
LitKind::from_token_lit(self.as_token_lit()).ok().and_then(|lit| lit.str())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AttributeExt: Debug {
|
||||
fn id(&self) -> AttrId;
|
||||
|
||||
fn name_or_empty(&self) -> Symbol {
|
||||
self.ident().unwrap_or_else(Ident::empty).name
|
||||
}
|
||||
|
||||
/// Get the meta item list, `#[attr(meta item list)]`
|
||||
fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>>;
|
||||
|
||||
/// Gets the value literal, as string, when using `#[attr = value]`
|
||||
fn value_str(&self) -> Option<Symbol>;
|
||||
|
||||
/// Gets the span of the value literal, as string, when using `#[attr = value]`
|
||||
fn value_span(&self) -> Option<Span>;
|
||||
|
||||
/// For a single-segment attribute, returns its name; otherwise, returns `None`.
|
||||
fn ident(&self) -> Option<Ident>;
|
||||
|
||||
/// Checks whether the path of this attribute matches the name.
|
||||
///
|
||||
/// Matches one segment of the path to each element in `name`
|
||||
fn path_matches(&self, name: &[Symbol]) -> bool;
|
||||
|
||||
/// Returns `true` if it is a sugared doc comment (`///` or `//!` for example).
|
||||
/// So `#[doc = "doc"]` (which is a doc comment) and `#[doc(...)]` (which is not
|
||||
/// a doc comment) will return `false`.
|
||||
fn is_doc_comment(&self) -> bool;
|
||||
|
||||
#[inline]
|
||||
fn has_name(&self, name: Symbol) -> bool {
|
||||
self.ident().map(|x| x.name == name).unwrap_or(false)
|
||||
}
|
||||
|
||||
/// get the span of the entire attribute
|
||||
fn span(&self) -> Span;
|
||||
|
||||
fn is_word(&self) -> bool;
|
||||
|
||||
fn path(&self) -> SmallVec<[Symbol; 1]> {
|
||||
self.ident_path()
|
||||
.map(|i| i.into_iter().map(|i| i.name).collect())
|
||||
.unwrap_or(smallvec![sym::doc])
|
||||
}
|
||||
|
||||
/// Returns None for doc comments
|
||||
fn ident_path(&self) -> Option<SmallVec<[Ident; 1]>>;
|
||||
|
||||
/// Returns the documentation if this is a doc comment or a sugared doc comment.
|
||||
/// * `///doc` returns `Some("doc")`.
|
||||
/// * `#[doc = "doc"]` returns `Some("doc")`.
|
||||
/// * `#[doc(...)]` returns `None`.
|
||||
fn doc_str(&self) -> Option<Symbol>;
|
||||
|
||||
fn is_proc_macro_attr(&self) -> bool {
|
||||
[sym::proc_macro, sym::proc_macro_attribute, sym::proc_macro_derive]
|
||||
.iter()
|
||||
.any(|kind| self.has_name(*kind))
|
||||
}
|
||||
|
||||
/// Returns the documentation and its kind if this is a doc comment or a sugared doc comment.
|
||||
/// * `///doc` returns `Some(("doc", CommentKind::Line))`.
|
||||
/// * `/** doc */` returns `Some(("doc", CommentKind::Block))`.
|
||||
/// * `#[doc = "doc"]` returns `Some(("doc", CommentKind::Line))`.
|
||||
/// * `#[doc(...)]` returns `None`.
|
||||
fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)>;
|
||||
|
||||
fn style(&self) -> AttrStyle;
|
||||
}
|
||||
|
||||
// FIXME(fn_delegation): use function delegation instead of manually forwarding
|
||||
|
||||
impl Attribute {
|
||||
pub fn id(&self) -> AttrId {
|
||||
AttributeExt::id(self)
|
||||
}
|
||||
|
||||
pub fn name_or_empty(&self) -> Symbol {
|
||||
AttributeExt::name_or_empty(self)
|
||||
}
|
||||
|
||||
pub fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> {
|
||||
AttributeExt::meta_item_list(self)
|
||||
}
|
||||
|
||||
pub fn value_str(&self) -> Option<Symbol> {
|
||||
AttributeExt::value_str(self)
|
||||
}
|
||||
|
||||
pub fn value_span(&self) -> Option<Span> {
|
||||
AttributeExt::value_span(self)
|
||||
}
|
||||
|
||||
pub fn ident(&self) -> Option<Ident> {
|
||||
AttributeExt::ident(self)
|
||||
}
|
||||
|
||||
pub fn path_matches(&self, name: &[Symbol]) -> bool {
|
||||
AttributeExt::path_matches(self, name)
|
||||
}
|
||||
|
||||
pub fn is_doc_comment(&self) -> bool {
|
||||
AttributeExt::is_doc_comment(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn has_name(&self, name: Symbol) -> bool {
|
||||
AttributeExt::has_name(self, name)
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Span {
|
||||
AttributeExt::span(self)
|
||||
}
|
||||
|
||||
pub fn is_word(&self) -> bool {
|
||||
AttributeExt::is_word(self)
|
||||
}
|
||||
|
||||
pub fn path(&self) -> SmallVec<[Symbol; 1]> {
|
||||
AttributeExt::path(self)
|
||||
}
|
||||
|
||||
pub fn ident_path(&self) -> Option<SmallVec<[Ident; 1]>> {
|
||||
AttributeExt::ident_path(self)
|
||||
}
|
||||
|
||||
pub fn doc_str(&self) -> Option<Symbol> {
|
||||
AttributeExt::doc_str(self)
|
||||
}
|
||||
|
||||
pub fn is_proc_macro_attr(&self) -> bool {
|
||||
AttributeExt::is_proc_macro_attr(self)
|
||||
}
|
||||
|
||||
pub fn doc_str_and_comment_kind(&self) -> Option<(Symbol, CommentKind)> {
|
||||
AttributeExt::doc_str_and_comment_kind(self)
|
||||
}
|
||||
|
||||
pub fn style(&self) -> AttrStyle {
|
||||
AttributeExt::style(self)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use rustc_span::Symbol;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{Symbol, sym};
|
||||
|
||||
use crate::{Attribute, attr};
|
||||
use crate::attr::{self, AttributeExt};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum EntryPointType {
|
||||
|
|
@ -37,7 +36,7 @@ pub enum EntryPointType {
|
|||
}
|
||||
|
||||
pub fn entry_point_type(
|
||||
attrs: &[Attribute],
|
||||
attrs: &[impl AttributeExt],
|
||||
at_root: bool,
|
||||
name: Option<Symbol>,
|
||||
) -> EntryPointType {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use rustc_macros::HashStable_Generic;
|
||||
use rustc_span::symbol::{Symbol, sym};
|
||||
use rustc_span::{Symbol, sym};
|
||||
|
||||
#[derive(Clone, Debug, Copy, Eq, PartialEq, HashStable_Generic)]
|
||||
pub enum AllocatorKind {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
//! Definitions shared by macros / syntax extensions and e.g. `rustc_middle`.
|
||||
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
|
||||
use rustc_span::Ident;
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_span::symbol::Ident;
|
||||
|
||||
use crate::MetaItem;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_macros::{Decodable, Encodable};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::{Ident, Symbol};
|
||||
use rustc_span::{Ident, Span, Symbol};
|
||||
|
||||
use crate::Expr;
|
||||
use crate::ptr::P;
|
||||
|
|
|
|||
|
|
@ -44,20 +44,10 @@ pub mod token;
|
|||
pub mod tokenstream;
|
||||
pub mod visit;
|
||||
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
|
||||
pub use self::ast::*;
|
||||
pub use self::ast_traits::{AstDeref, AstNodeWrapper, HasAttrs, HasNodeId, HasTokens};
|
||||
|
||||
/// Requirements for a `StableHashingContext` to be used in this crate.
|
||||
/// This is a hack to allow using the `HashStable_Generic` derive macro
|
||||
/// instead of implementing everything in `rustc_middle`.
|
||||
pub trait HashStableContext: rustc_span::HashStableContext {
|
||||
fn hash_attr(&mut self, _: &ast::Attribute, hasher: &mut StableHasher);
|
||||
}
|
||||
|
||||
impl<AstCtx: crate::HashStableContext> HashStable<AstCtx> for ast::Attribute {
|
||||
fn hash_stable(&self, hcx: &mut AstCtx, hasher: &mut StableHasher) {
|
||||
hcx.hash_attr(self, hasher)
|
||||
}
|
||||
}
|
||||
pub trait HashStableContext: rustc_span::HashStableContext {}
|
||||
|
|
|
|||
|
|
@ -13,9 +13,8 @@ use std::panic;
|
|||
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{Ident, Span};
|
||||
use smallvec::{Array, SmallVec, smallvec};
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
|
|
@ -451,8 +450,8 @@ fn visit_attr_args<T: MutVisitor>(vis: &mut T, args: &mut AttrArgs) {
|
|||
match args {
|
||||
AttrArgs::Empty => {}
|
||||
AttrArgs::Delimited(args) => visit_delim_args(vis, args),
|
||||
AttrArgs::Eq { eq_span, value } => {
|
||||
vis.visit_expr(value.unwrap_ast_mut());
|
||||
AttrArgs::Eq { eq_span, expr } => {
|
||||
vis.visit_expr(expr);
|
||||
vis.visit_span(eq_span);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,11 +11,10 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
|||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, kw, sym};
|
||||
#[allow(clippy::useless_attribute)] // FIXME: following use of `hidden_glob_reexports` incorrectly triggers `useless_attribute` lint.
|
||||
#[allow(hidden_glob_reexports)]
|
||||
use rustc_span::symbol::{Ident, Symbol};
|
||||
use rustc_span::symbol::{kw, sym};
|
||||
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
|
||||
use rustc_span::{Ident, Symbol};
|
||||
|
||||
use crate::ast;
|
||||
use crate::ptr::P;
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ use std::{ascii, fmt, str};
|
|||
use rustc_lexer::unescape::{
|
||||
MixedUnit, Mode, byte_from_char, unescape_byte, unescape_char, unescape_mixed, unescape_unicode,
|
||||
};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::{Symbol, kw, sym};
|
||||
use rustc_span::{Span, Symbol, kw, sym};
|
||||
use tracing::debug;
|
||||
|
||||
use crate::ast::{self, LitKind, MetaItemLit, StrStyle};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use rustc_span::symbol::kw;
|
||||
use rustc_span::kw;
|
||||
|
||||
use crate::ast::{self, BinOpKind};
|
||||
use crate::token::{self, BinOpToken, Token};
|
||||
|
|
|
|||
|
|
@ -15,8 +15,7 @@
|
|||
|
||||
pub use rustc_ast_ir::visit::VisitorResult;
|
||||
pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{Ident, Span};
|
||||
|
||||
use crate::ast::*;
|
||||
use crate::ptr::P;
|
||||
|
|
@ -1287,7 +1286,7 @@ pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) -
|
|||
match args {
|
||||
AttrArgs::Empty => {}
|
||||
AttrArgs::Delimited(_args) => {}
|
||||
AttrArgs::Eq { value, .. } => try_visit!(visitor.visit_expr(value.unwrap_ast())),
|
||||
AttrArgs::Eq { expr, .. } => try_visit!(visitor.visit_expr(expr)),
|
||||
}
|
||||
V::Result::output()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
|||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::symbol::kw;
|
||||
use rustc_span::{Span, sym};
|
||||
use rustc_span::{Span, kw, sym};
|
||||
use rustc_target::asm;
|
||||
|
||||
use super::LoweringContext;
|
||||
|
|
|
|||
|
|
@ -46,8 +46,7 @@ use rustc_errors::ErrorGuaranteed;
|
|||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::{Asyncness, ResolverAstLowering};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{Ident, Span};
|
||||
use rustc_target::spec::abi;
|
||||
use {rustc_ast as ast, rustc_hir as hir};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{Diag, DiagArgFromDisplay, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_span::{Ident, Span, Symbol};
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_lowering_generic_type_with_parentheses, code = E0214)]
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@ use rustc_middle::span_bug;
|
|||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::errors::report_lit_error;
|
||||
use rustc_span::source_map::{Spanned, respan};
|
||||
use rustc_span::symbol::{Ident, Symbol, kw, sym};
|
||||
use rustc_span::{DUMMY_SP, DesugaringKind, Span};
|
||||
use rustc_span::{DUMMY_SP, DesugaringKind, Ident, Span, Symbol, kw, sym};
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
use visit::{Visitor, walk_expr};
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@ use rustc_ast::*;
|
|||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_hir as hir;
|
||||
use rustc_session::config::FmtDebug;
|
||||
use rustc_span::symbol::{Ident, kw};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
use rustc_span::{Ident, Span, Symbol, kw, sym};
|
||||
|
||||
use super::LoweringContext;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ use rustc_index::{IndexSlice, IndexVec};
|
|||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
|
||||
use rustc_span::edit_distance::find_best_match_for_name;
|
||||
use rustc_span::symbol::{Ident, kw, sym};
|
||||
use rustc_span::{DesugaringKind, Span, Symbol};
|
||||
use rustc_span::{DesugaringKind, Ident, Span, Symbol, kw, sym};
|
||||
use rustc_target::spec::abi;
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use thin_vec::ThinVec;
|
||||
|
|
@ -176,7 +175,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
id: NodeId,
|
||||
hir_id: hir::HirId,
|
||||
ident: &mut Ident,
|
||||
attrs: &'hir [Attribute],
|
||||
attrs: &'hir [hir::Attribute],
|
||||
vis_span: Span,
|
||||
i: &ItemKind,
|
||||
) -> hir::ItemKind<'hir> {
|
||||
|
|
@ -467,7 +466,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
id: NodeId,
|
||||
vis_span: Span,
|
||||
ident: &mut Ident,
|
||||
attrs: &'hir [Attribute],
|
||||
attrs: &'hir [hir::Attribute],
|
||||
) -> hir::ItemKind<'hir> {
|
||||
let path = &tree.prefix;
|
||||
let segments = prefix.segments.iter().chain(path.segments.iter()).cloned().collect();
|
||||
|
|
@ -1172,9 +1171,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// we can keep the same name for the parameter.
|
||||
// This lets rustdoc render it correctly in documentation.
|
||||
hir::PatKind::Binding(_, _, ident, _) => (ident, false),
|
||||
hir::PatKind::Wild => {
|
||||
(Ident::with_dummy_span(rustc_span::symbol::kw::Underscore), false)
|
||||
}
|
||||
hir::PatKind::Wild => (Ident::with_dummy_span(rustc_span::kw::Underscore), false),
|
||||
_ => {
|
||||
// Replace the ident for bindings that aren't simple.
|
||||
let name = format!("__arg{index}");
|
||||
|
|
@ -1392,7 +1389,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn lower_safety(&mut self, s: Safety, default: hir::Safety) -> hir::Safety {
|
||||
pub(super) fn lower_safety(&self, s: Safety, default: hir::Safety) -> hir::Safety {
|
||||
match s {
|
||||
Safety::Unsafe(_) => hir::Safety::Unsafe,
|
||||
Safety::Default => default,
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@
|
|||
// tidy-alphabetical-end
|
||||
|
||||
use rustc_ast::node_id::NodeMap;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{self as ast, *};
|
||||
use rustc_data_structures::captures::Captures;
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
|
|
@ -59,8 +58,7 @@ use rustc_macros::extension;
|
|||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
|
||||
use rustc_session::parse::{add_feature_diagnostics, feature_err};
|
||||
use rustc_span::symbol::{Ident, Symbol, kw, sym};
|
||||
use rustc_span::{DUMMY_SP, DesugaringKind, Span};
|
||||
use rustc_span::{DUMMY_SP, DesugaringKind, Ident, Span, Symbol, kw, sym};
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use thin_vec::ThinVec;
|
||||
use tracing::{debug, instrument, trace};
|
||||
|
|
@ -96,7 +94,7 @@ struct LoweringContext<'a, 'hir> {
|
|||
/// Bodies inside the owner being lowered.
|
||||
bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>,
|
||||
/// Attributes inside the owner being lowered.
|
||||
attrs: SortedMap<hir::ItemLocalId, &'hir [Attribute]>,
|
||||
attrs: SortedMap<hir::ItemLocalId, &'hir [hir::Attribute]>,
|
||||
/// Collect items that were created by lowering the current owner.
|
||||
children: Vec<(LocalDefId, hir::MaybeOwner<'hir>)>,
|
||||
|
||||
|
|
@ -847,7 +845,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
ret
|
||||
}
|
||||
|
||||
fn lower_attrs(&mut self, id: HirId, attrs: &[Attribute]) -> &'hir [Attribute] {
|
||||
fn lower_attrs(&mut self, id: HirId, attrs: &[Attribute]) -> &'hir [hir::Attribute] {
|
||||
if attrs.is_empty() {
|
||||
&[]
|
||||
} else {
|
||||
|
|
@ -859,25 +857,33 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
fn lower_attr(&self, attr: &Attribute) -> Attribute {
|
||||
fn lower_attr(&self, attr: &Attribute) -> hir::Attribute {
|
||||
// Note that we explicitly do not walk the path. Since we don't really
|
||||
// lower attributes (we use the AST version) there is nowhere to keep
|
||||
// the `HirId`s. We don't actually need HIR version of attributes anyway.
|
||||
// Tokens are also not needed after macro expansion and parsing.
|
||||
let kind = match attr.kind {
|
||||
AttrKind::Normal(ref normal) => AttrKind::Normal(P(NormalAttr {
|
||||
item: AttrItem {
|
||||
unsafety: normal.item.unsafety,
|
||||
path: normal.item.path.clone(),
|
||||
args: self.lower_attr_args(&normal.item.args),
|
||||
tokens: None,
|
||||
AttrKind::Normal(ref normal) => hir::AttrKind::Normal(Box::new(hir::AttrItem {
|
||||
unsafety: self.lower_safety(normal.item.unsafety, hir::Safety::Safe),
|
||||
path: hir::AttrPath {
|
||||
segments: normal
|
||||
.item
|
||||
.path
|
||||
.segments
|
||||
.iter()
|
||||
.map(|i| i.ident)
|
||||
.collect::<Vec<_>>()
|
||||
.into_boxed_slice(),
|
||||
span: normal.item.path.span,
|
||||
},
|
||||
tokens: None,
|
||||
args: self.lower_attr_args(&normal.item.args),
|
||||
})),
|
||||
AttrKind::DocComment(comment_kind, data) => AttrKind::DocComment(comment_kind, data),
|
||||
AttrKind::DocComment(comment_kind, data) => {
|
||||
hir::AttrKind::DocComment(comment_kind, data)
|
||||
}
|
||||
};
|
||||
|
||||
Attribute { kind, id: attr.id, style: attr.style, span: self.lower_span(attr.span) }
|
||||
hir::Attribute { kind, id: attr.id, style: attr.style, span: self.lower_span(attr.span) }
|
||||
}
|
||||
|
||||
fn alias_attrs(&mut self, id: HirId, target_id: HirId) {
|
||||
|
|
@ -889,15 +895,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
}
|
||||
|
||||
fn lower_attr_args(&self, args: &AttrArgs) -> AttrArgs {
|
||||
fn lower_attr_args(&self, args: &AttrArgs) -> hir::AttrArgs {
|
||||
match args {
|
||||
AttrArgs::Empty => AttrArgs::Empty,
|
||||
AttrArgs::Delimited(args) => AttrArgs::Delimited(self.lower_delim_args(args)),
|
||||
AttrArgs::Empty => hir::AttrArgs::Empty,
|
||||
AttrArgs::Delimited(args) => hir::AttrArgs::Delimited(self.lower_delim_args(args)),
|
||||
// This is an inert key-value attribute - it will never be visible to macros
|
||||
// after it gets lowered to HIR. Therefore, we can extract literals to handle
|
||||
// nonterminals in `#[doc]` (e.g. `#[doc = $e]`).
|
||||
&AttrArgs::Eq { eq_span, ref value } => {
|
||||
let expr = value.unwrap_ast();
|
||||
&AttrArgs::Eq { eq_span, ref expr } => {
|
||||
// In valid code the value always ends up as a single literal. Otherwise, a dummy
|
||||
// literal suffices because the error is handled elsewhere.
|
||||
let lit = if let ExprKind::Lit(token_lit) = expr.kind
|
||||
|
|
@ -913,7 +918,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
span: DUMMY_SP,
|
||||
}
|
||||
};
|
||||
AttrArgs::Eq { eq_span, value: AttrArgsEq::Hir(lit) }
|
||||
hir::AttrArgs::Eq { eq_span, expr: lit }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2201,7 +2206,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
|
||||
fn stmt_let_pat(
|
||||
&mut self,
|
||||
attrs: Option<&'hir [Attribute]>,
|
||||
attrs: Option<&'hir [hir::Attribute]>,
|
||||
span: Span,
|
||||
init: Option<&'hir hir::Expr<'hir>>,
|
||||
pat: &'hir hir::Pat<'hir>,
|
||||
|
|
|
|||
|
|
@ -3,9 +3,8 @@ use rustc_ast::*;
|
|||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{Ident, Span};
|
||||
|
||||
use super::errors::{
|
||||
ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding,
|
||||
|
|
@ -92,7 +91,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
span: self.lower_span(f.span),
|
||||
}
|
||||
}));
|
||||
break hir::PatKind::Struct(qpath, fs, *etc == ast::PatFieldsRest::Rest);
|
||||
break hir::PatKind::Struct(
|
||||
qpath,
|
||||
fs,
|
||||
matches!(
|
||||
etc,
|
||||
ast::PatFieldsRest::Rest | ast::PatFieldsRest::Recovered(_)
|
||||
),
|
||||
);
|
||||
}
|
||||
PatKind::Tuple(pats) => {
|
||||
let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple");
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@ use rustc_hir::def::{DefKind, PartialRes, Res};
|
|||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_session::parse::add_feature_diagnostics;
|
||||
use rustc_span::symbol::{Ident, kw, sym};
|
||||
use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Span, Symbol};
|
||||
use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, kw, sym};
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ edition = "2021"
|
|||
itertools = "0.12"
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||
rustc_attr = { path = "../rustc_attr" }
|
||||
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_feature = { path = "../rustc_feature" }
|
||||
|
|
|
|||
|
|
@ -34,8 +34,7 @@ use rustc_session::lint::builtin::{
|
|||
PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||
};
|
||||
use rustc_session::lint::{BuiltinLintDiag, LintBuffer};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::{Ident, kw, sym};
|
||||
use rustc_span::{Ident, Span, kw, sym};
|
||||
use rustc_target::spec::abi;
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
|
|
@ -342,7 +341,7 @@ impl<'a> AstValidator<'a> {
|
|||
sym::forbid,
|
||||
sym::warn,
|
||||
];
|
||||
!arr.contains(&attr.name_or_empty()) && rustc_attr::is_builtin_attr(attr)
|
||||
!arr.contains(&attr.name_or_empty()) && rustc_attr_parsing::is_builtin_attr(*attr)
|
||||
})
|
||||
.for_each(|attr| {
|
||||
if attr.is_doc_comment() {
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@ use rustc_ast::ParamKindOrd;
|
|||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{Applicability, Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_span::{Ident, Span, Symbol};
|
||||
|
||||
use crate::fluent_generated as fluent;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,8 @@ use rustc_ast::{NodeId, PatKind, attr, token};
|
|||
use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, Features, GateIssue};
|
||||
use rustc_session::Session;
|
||||
use rustc_session::parse::{feature_err, feature_err_issue, feature_warn};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::{Symbol, sym};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
use rustc_target::spec::abi;
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
|
|
|
|||
|
|
@ -17,15 +17,15 @@ use rustc_ast::tokenstream::{Spacing, TokenStream, TokenTree};
|
|||
use rustc_ast::util::classify;
|
||||
use rustc_ast::util::comments::{Comment, CommentStyle};
|
||||
use rustc_ast::{
|
||||
self as ast, AttrArgs, AttrArgsEq, BindingMode, BlockCheckMode, ByRef, DelimArgs, GenericArg,
|
||||
GenericBound, InlineAsmOperand, InlineAsmOptions, InlineAsmRegOrRegClass,
|
||||
InlineAsmTemplatePiece, PatKind, RangeEnd, RangeSyntax, Safety, SelfKind, Term, attr,
|
||||
self as ast, AttrArgs, BindingMode, BlockCheckMode, ByRef, DelimArgs, GenericArg, GenericBound,
|
||||
InlineAsmOperand, InlineAsmOptions, InlineAsmRegOrRegClass, InlineAsmTemplatePiece, PatKind,
|
||||
RangeEnd, RangeSyntax, Safety, SelfKind, Term, attr,
|
||||
};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::source_map::{SourceMap, Spanned};
|
||||
use rustc_span::symbol::{Ident, IdentPrinter, Symbol, kw, sym};
|
||||
use rustc_span::{BytePos, CharPos, DUMMY_SP, FileName, Pos, Span};
|
||||
use rustc_span::symbol::IdentPrinter;
|
||||
use rustc_span::{BytePos, CharPos, DUMMY_SP, FileName, Ident, Pos, Span, Symbol, kw, sym};
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
use crate::pp::Breaks::{Consistent, Inconsistent};
|
||||
|
|
@ -359,7 +359,7 @@ fn binop_to_string(op: BinOpToken) -> &'static str {
|
|||
}
|
||||
}
|
||||
|
||||
fn doc_comment_to_string(
|
||||
pub fn doc_comment_to_string(
|
||||
comment_kind: CommentKind,
|
||||
attr_style: ast::AttrStyle,
|
||||
data: Symbol,
|
||||
|
|
@ -648,20 +648,13 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
|
|||
AttrArgs::Empty => {
|
||||
self.print_path(&item.path, false, 0);
|
||||
}
|
||||
AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => {
|
||||
AttrArgs::Eq { expr, .. } => {
|
||||
self.print_path(&item.path, false, 0);
|
||||
self.space();
|
||||
self.word_space("=");
|
||||
let token_str = self.expr_to_string(expr);
|
||||
self.word(token_str);
|
||||
}
|
||||
AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => {
|
||||
self.print_path(&item.path, false, 0);
|
||||
self.space();
|
||||
self.word_space("=");
|
||||
let token_str = self.meta_item_lit_to_string(lit);
|
||||
self.word(token_str);
|
||||
}
|
||||
}
|
||||
match item.unsafety {
|
||||
ast::Safety::Unsafe(_) => self.pclose(),
|
||||
|
|
@ -1661,11 +1654,14 @@ impl<'a> State<'a> {
|
|||
},
|
||||
|f| f.pat.span,
|
||||
);
|
||||
if *etc == ast::PatFieldsRest::Rest {
|
||||
if let ast::PatFieldsRest::Rest | ast::PatFieldsRest::Recovered(_) = etc {
|
||||
if !fields.is_empty() {
|
||||
self.word_space(",");
|
||||
}
|
||||
self.word("..");
|
||||
if let ast::PatFieldsRest::Recovered(_) = etc {
|
||||
self.word("/* recovered parse error */");
|
||||
}
|
||||
}
|
||||
if !empty {
|
||||
self.space();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use itertools::{Itertools, Position};
|
|||
use rustc_ast as ast;
|
||||
use rustc_ast::ModKind;
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::Ident;
|
||||
|
||||
use crate::pp::Breaks::Inconsistent;
|
||||
use crate::pprust::state::fixup::FixupContext;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use rustc_ast as ast;
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{DUMMY_SP, create_default_session_globals_then};
|
||||
use rustc_span::{DUMMY_SP, Ident, create_default_session_globals_then};
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
use super::*;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "rustc_attr"
|
||||
name = "rustc_attr_data_structures"
|
||||
version = "0.0.0"
|
||||
edition = "2021"
|
||||
|
||||
106
compiler/rustc_attr_data_structures/src/attributes.rs
Normal file
106
compiler/rustc_attr_data_structures/src/attributes.rs
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
use rustc_abi::Align;
|
||||
use rustc_ast as ast;
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
|
||||
use rustc_span::{Span, Symbol};
|
||||
|
||||
use crate::RustcVersion;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
pub enum InlineAttr {
|
||||
None,
|
||||
Hint,
|
||||
Always,
|
||||
Never,
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq, HashStable_Generic)]
|
||||
pub enum InstructionSetAttr {
|
||||
ArmA32,
|
||||
ArmT32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
pub enum OptimizeAttr {
|
||||
None,
|
||||
Speed,
|
||||
Size,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Encodable, Decodable)]
|
||||
pub enum DiagnosticAttribute {
|
||||
// tidy-alphabetical-start
|
||||
DoNotRecommend,
|
||||
OnUnimplemented,
|
||||
// tidy-alphabetical-end
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug, Encodable, Decodable, Copy, Clone)]
|
||||
pub enum ReprAttr {
|
||||
ReprInt(IntType),
|
||||
ReprRust,
|
||||
ReprC,
|
||||
ReprPacked(Align),
|
||||
ReprSimd,
|
||||
ReprTransparent,
|
||||
ReprAlign(Align),
|
||||
}
|
||||
pub use ReprAttr::*;
|
||||
|
||||
pub enum TransparencyError {
|
||||
UnknownTransparency(Symbol, Span),
|
||||
MultipleTransparencyAttrs(Span, Span),
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
|
||||
#[derive(Encodable, Decodable)]
|
||||
pub enum IntType {
|
||||
SignedInt(ast::IntTy),
|
||||
UnsignedInt(ast::UintTy),
|
||||
}
|
||||
|
||||
#[derive(Copy, Debug, Encodable, Decodable, Clone, HashStable_Generic)]
|
||||
pub struct Deprecation {
|
||||
pub since: DeprecatedSince,
|
||||
/// The note to issue a reason.
|
||||
pub note: Option<Symbol>,
|
||||
/// A text snippet used to completely replace any use of the deprecated item in an expression.
|
||||
///
|
||||
/// This is currently unstable.
|
||||
pub suggestion: Option<Symbol>,
|
||||
}
|
||||
|
||||
/// Release in which an API is deprecated.
|
||||
#[derive(Copy, Debug, Encodable, Decodable, Clone, HashStable_Generic)]
|
||||
pub enum DeprecatedSince {
|
||||
RustcVersion(RustcVersion),
|
||||
/// Deprecated in the future ("to be determined").
|
||||
Future,
|
||||
/// `feature(staged_api)` is off. Deprecation versions outside the standard
|
||||
/// library are allowed to be arbitrary strings, for better or worse.
|
||||
NonStandard(Symbol),
|
||||
/// Deprecation version is unspecified but optional.
|
||||
Unspecified,
|
||||
/// Failed to parse a deprecation version, or the deprecation version is
|
||||
/// unspecified and required. An error has already been emitted.
|
||||
Err,
|
||||
}
|
||||
|
||||
impl Deprecation {
|
||||
/// Whether an item marked with #[deprecated(since = "X")] is currently
|
||||
/// deprecated (i.e., whether X is not greater than the current rustc
|
||||
/// version).
|
||||
pub fn is_in_effect(&self) -> bool {
|
||||
match self.since {
|
||||
DeprecatedSince::RustcVersion(since) => since <= RustcVersion::CURRENT,
|
||||
DeprecatedSince::Future => false,
|
||||
// The `since` field doesn't have semantic purpose without `#![staged_api]`.
|
||||
DeprecatedSince::NonStandard(_) => true,
|
||||
// Assume deprecation is in effect if "since" field is absent or invalid.
|
||||
DeprecatedSince::Unspecified | DeprecatedSince::Err => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_since_rustc_version(&self) -> bool {
|
||||
matches!(self.since, DeprecatedSince::RustcVersion(_))
|
||||
}
|
||||
}
|
||||
16
compiler/rustc_attr_data_structures/src/lib.rs
Normal file
16
compiler/rustc_attr_data_structures/src/lib.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![warn(unreachable_pub)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
mod attributes;
|
||||
mod stability;
|
||||
mod version;
|
||||
|
||||
pub use attributes::*;
|
||||
pub(crate) use rustc_session::HashStableContext;
|
||||
pub use stability::*;
|
||||
pub use version::*;
|
||||
200
compiler/rustc_attr_data_structures/src/stability.rs
Normal file
200
compiler/rustc_attr_data_structures/src/stability.rs
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
use std::num::NonZero;
|
||||
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
|
||||
use rustc_span::{Symbol, sym};
|
||||
|
||||
use crate::RustcVersion;
|
||||
|
||||
/// The version placeholder that recently stabilized features contain inside the
|
||||
/// `since` field of the `#[stable]` attribute.
|
||||
///
|
||||
/// For more, see [this pull request](https://github.com/rust-lang/rust/pull/100591).
|
||||
pub const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION";
|
||||
|
||||
/// Represents the following attributes:
|
||||
///
|
||||
/// - `#[stable]`
|
||||
/// - `#[unstable]`
|
||||
#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(HashStable_Generic)]
|
||||
pub struct Stability {
|
||||
pub level: StabilityLevel,
|
||||
pub feature: Symbol,
|
||||
}
|
||||
|
||||
impl Stability {
|
||||
pub fn is_unstable(&self) -> bool {
|
||||
self.level.is_unstable()
|
||||
}
|
||||
|
||||
pub fn is_stable(&self) -> bool {
|
||||
self.level.is_stable()
|
||||
}
|
||||
|
||||
pub fn stable_since(&self) -> Option<StableSince> {
|
||||
self.level.stable_since()
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the `#[rustc_const_unstable]` and `#[rustc_const_stable]` attributes.
|
||||
#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(HashStable_Generic)]
|
||||
pub struct ConstStability {
|
||||
pub level: StabilityLevel,
|
||||
pub feature: Symbol,
|
||||
/// whether the function has a `#[rustc_promotable]` attribute
|
||||
pub promotable: bool,
|
||||
/// This is true iff the `const_stable_indirect` attribute is present.
|
||||
pub const_stable_indirect: bool,
|
||||
}
|
||||
|
||||
impl ConstStability {
|
||||
pub fn from_partial(
|
||||
PartialConstStability { level, feature, promotable }: PartialConstStability,
|
||||
const_stable_indirect: bool,
|
||||
) -> Self {
|
||||
Self { const_stable_indirect, level, feature, promotable }
|
||||
}
|
||||
|
||||
/// The stability assigned to unmarked items when -Zforce-unstable-if-unmarked is set.
|
||||
pub fn unmarked(const_stable_indirect: bool, regular_stab: Stability) -> Self {
|
||||
Self {
|
||||
feature: regular_stab.feature,
|
||||
promotable: false,
|
||||
level: regular_stab.level,
|
||||
const_stable_indirect,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_const_unstable(&self) -> bool {
|
||||
self.level.is_unstable()
|
||||
}
|
||||
|
||||
pub fn is_const_stable(&self) -> bool {
|
||||
self.level.is_stable()
|
||||
}
|
||||
}
|
||||
|
||||
/// Excludes `const_stable_indirect`. This is necessary because when `-Zforce-unstable-if-unmarked`
|
||||
/// is set, we need to encode standalone `#[rustc_const_stable_indirect]` attributes
|
||||
#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(HashStable_Generic)]
|
||||
pub struct PartialConstStability {
|
||||
pub level: StabilityLevel,
|
||||
pub feature: Symbol,
|
||||
/// whether the function has a `#[rustc_promotable]` attribute
|
||||
pub promotable: bool,
|
||||
}
|
||||
|
||||
impl PartialConstStability {
|
||||
pub fn is_const_unstable(&self) -> bool {
|
||||
self.level.is_unstable()
|
||||
}
|
||||
|
||||
pub fn is_const_stable(&self) -> bool {
|
||||
self.level.is_stable()
|
||||
}
|
||||
}
|
||||
|
||||
/// The available stability levels.
|
||||
#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]
|
||||
#[derive(HashStable_Generic)]
|
||||
pub enum StabilityLevel {
|
||||
/// `#[unstable]`
|
||||
Unstable {
|
||||
/// Reason for the current stability level.
|
||||
reason: UnstableReason,
|
||||
/// Relevant `rust-lang/rust` issue.
|
||||
issue: Option<NonZero<u32>>,
|
||||
is_soft: bool,
|
||||
/// If part of a feature is stabilized and a new feature is added for the remaining parts,
|
||||
/// then the `implied_by` attribute is used to indicate which now-stable feature previously
|
||||
/// contained an item.
|
||||
///
|
||||
/// ```pseudo-Rust
|
||||
/// #[unstable(feature = "foo", issue = "...")]
|
||||
/// fn foo() {}
|
||||
/// #[unstable(feature = "foo", issue = "...")]
|
||||
/// fn foobar() {}
|
||||
/// ```
|
||||
///
|
||||
/// ...becomes...
|
||||
///
|
||||
/// ```pseudo-Rust
|
||||
/// #[stable(feature = "foo", since = "1.XX.X")]
|
||||
/// fn foo() {}
|
||||
/// #[unstable(feature = "foobar", issue = "...", implied_by = "foo")]
|
||||
/// fn foobar() {}
|
||||
/// ```
|
||||
implied_by: Option<Symbol>,
|
||||
},
|
||||
/// `#[stable]`
|
||||
Stable {
|
||||
/// Rust release which stabilized this feature.
|
||||
since: StableSince,
|
||||
/// Is this item allowed to be referred to on stable, despite being contained in unstable
|
||||
/// modules?
|
||||
allowed_through_unstable_modules: bool,
|
||||
},
|
||||
}
|
||||
|
||||
/// Rust release in which a feature is stabilized.
|
||||
#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(HashStable_Generic)]
|
||||
pub enum StableSince {
|
||||
/// also stores the original symbol for printing
|
||||
Version(RustcVersion),
|
||||
/// Stabilized in the upcoming version, whatever number that is.
|
||||
Current,
|
||||
/// Failed to parse a stabilization version.
|
||||
Err,
|
||||
}
|
||||
|
||||
impl StabilityLevel {
|
||||
pub fn is_unstable(&self) -> bool {
|
||||
matches!(self, StabilityLevel::Unstable { .. })
|
||||
}
|
||||
pub fn is_stable(&self) -> bool {
|
||||
matches!(self, StabilityLevel::Stable { .. })
|
||||
}
|
||||
pub fn stable_since(&self) -> Option<StableSince> {
|
||||
match *self {
|
||||
StabilityLevel::Stable { since, .. } => Some(since),
|
||||
StabilityLevel::Unstable { .. } => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]
|
||||
#[derive(HashStable_Generic)]
|
||||
pub enum UnstableReason {
|
||||
None,
|
||||
Default,
|
||||
Some(Symbol),
|
||||
}
|
||||
|
||||
/// Represents the `#[rustc_default_body_unstable]` attribute.
|
||||
#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(HashStable_Generic)]
|
||||
pub struct DefaultBodyStability {
|
||||
pub level: StabilityLevel,
|
||||
pub feature: Symbol,
|
||||
}
|
||||
|
||||
impl UnstableReason {
|
||||
pub fn from_opt_reason(reason: Option<Symbol>) -> Self {
|
||||
// UnstableReason::Default constructed manually
|
||||
match reason {
|
||||
Some(r) => Self::Some(r),
|
||||
None => Self::None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_opt_reason(&self) -> Option<Symbol> {
|
||||
match self {
|
||||
Self::None => None,
|
||||
Self::Default => Some(sym::unstable_location_reason_default),
|
||||
Self::Some(r) => Some(*r),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
use std::borrow::Cow;
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
use rustc_errors::IntoDiagArg;
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_Generic, current_rustc_version};
|
||||
|
||||
#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
|
|
@ -21,9 +19,3 @@ impl Display for RustcVersion {
|
|||
write!(formatter, "{}.{}.{}", self.major, self.minor, self.patch)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoDiagArg for RustcVersion {
|
||||
fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
|
||||
rustc_errors::DiagArgValue::Str(Cow::Owned(self.to_string()))
|
||||
}
|
||||
}
|
||||
21
compiler/rustc_attr_parsing/Cargo.toml
Normal file
21
compiler/rustc_attr_parsing/Cargo.toml
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
[package]
|
||||
name = "rustc_attr_parsing"
|
||||
version = "0.0.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
rustc_abi = { path = "../rustc_abi" }
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||
rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_feature = { path = "../rustc_feature" }
|
||||
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
|
||||
rustc_lexer = { path = "../rustc_lexer" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_serialize = { path = "../rustc_serialize" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
# tidy-alphabetical-end
|
||||
|
|
@ -1,46 +1,46 @@
|
|||
attr_cfg_predicate_identifier =
|
||||
attr_parsing_cfg_predicate_identifier =
|
||||
`cfg` predicate key must be an identifier
|
||||
|
||||
attr_deprecated_item_suggestion =
|
||||
attr_parsing_deprecated_item_suggestion =
|
||||
suggestions on deprecated items are unstable
|
||||
.help = add `#![feature(deprecated_suggestion)]` to the crate root
|
||||
.note = see #94785 for more details
|
||||
|
||||
attr_expected_one_cfg_pattern =
|
||||
attr_parsing_expected_one_cfg_pattern =
|
||||
expected 1 cfg-pattern
|
||||
|
||||
attr_expected_single_version_literal =
|
||||
attr_parsing_expected_single_version_literal =
|
||||
expected single version literal
|
||||
|
||||
attr_expected_version_literal =
|
||||
attr_parsing_expected_version_literal =
|
||||
expected a version literal
|
||||
|
||||
attr_expects_feature_list =
|
||||
attr_parsing_expects_feature_list =
|
||||
`{$name}` expects a list of feature names
|
||||
|
||||
attr_expects_features =
|
||||
attr_parsing_expects_features =
|
||||
`{$name}` expects feature names
|
||||
|
||||
attr_incorrect_meta_item =
|
||||
attr_parsing_incorrect_meta_item =
|
||||
incorrect meta item
|
||||
|
||||
attr_incorrect_repr_format_align_one_arg =
|
||||
attr_parsing_incorrect_repr_format_align_one_arg =
|
||||
incorrect `repr(align)` attribute format: `align` takes exactly one argument in parentheses
|
||||
|
||||
attr_incorrect_repr_format_expect_literal_integer =
|
||||
attr_parsing_incorrect_repr_format_expect_literal_integer =
|
||||
incorrect `repr(align)` attribute format: `align` expects a literal integer as argument
|
||||
|
||||
attr_incorrect_repr_format_generic =
|
||||
attr_parsing_incorrect_repr_format_generic =
|
||||
incorrect `repr({$repr_arg})` attribute format
|
||||
.suggestion = use parentheses instead
|
||||
|
||||
attr_incorrect_repr_format_packed_expect_integer =
|
||||
attr_parsing_incorrect_repr_format_packed_expect_integer =
|
||||
incorrect `repr(packed)` attribute format: `packed` expects a literal integer as argument
|
||||
|
||||
attr_incorrect_repr_format_packed_one_or_zero_arg =
|
||||
attr_parsing_incorrect_repr_format_packed_one_or_zero_arg =
|
||||
incorrect `repr(packed)` attribute format: `packed` takes exactly one parenthesized argument, or no parentheses at all
|
||||
|
||||
attr_invalid_issue_string =
|
||||
attr_parsing_invalid_issue_string =
|
||||
`issue` must be a non-zero numeric string or "none"
|
||||
.must_not_be_zero = `issue` must not be "0", use "none" instead
|
||||
.empty = cannot parse integer from empty string
|
||||
|
|
@ -48,77 +48,77 @@ attr_invalid_issue_string =
|
|||
.pos_overflow = number too large to fit in target type
|
||||
.neg_overflow = number too small to fit in target type
|
||||
|
||||
attr_invalid_predicate =
|
||||
attr_parsing_invalid_predicate =
|
||||
invalid predicate `{$predicate}`
|
||||
|
||||
attr_invalid_repr_align_need_arg =
|
||||
attr_parsing_invalid_repr_align_need_arg =
|
||||
invalid `repr(align)` attribute: `align` needs an argument
|
||||
.suggestion = supply an argument here
|
||||
|
||||
attr_invalid_repr_generic =
|
||||
attr_parsing_invalid_repr_generic =
|
||||
invalid `repr({$repr_arg})` attribute: {$error_part}
|
||||
|
||||
attr_invalid_repr_hint_no_paren =
|
||||
attr_parsing_invalid_repr_hint_no_paren =
|
||||
invalid representation hint: `{$name}` does not take a parenthesized argument list
|
||||
|
||||
attr_invalid_repr_hint_no_value =
|
||||
attr_parsing_invalid_repr_hint_no_value =
|
||||
invalid representation hint: `{$name}` does not take a value
|
||||
|
||||
attr_invalid_since =
|
||||
attr_parsing_invalid_since =
|
||||
'since' must be a Rust version number, such as "1.31.0"
|
||||
|
||||
attr_missing_feature =
|
||||
attr_parsing_missing_feature =
|
||||
missing 'feature'
|
||||
|
||||
attr_missing_issue =
|
||||
attr_parsing_missing_issue =
|
||||
missing 'issue'
|
||||
|
||||
attr_missing_note =
|
||||
attr_parsing_missing_note =
|
||||
missing 'note'
|
||||
|
||||
attr_missing_since =
|
||||
attr_parsing_missing_since =
|
||||
missing 'since'
|
||||
|
||||
attr_multiple_item =
|
||||
attr_parsing_multiple_item =
|
||||
multiple '{$item}' items
|
||||
|
||||
attr_multiple_stability_levels =
|
||||
attr_parsing_multiple_stability_levels =
|
||||
multiple stability levels
|
||||
|
||||
attr_non_ident_feature =
|
||||
attr_parsing_non_ident_feature =
|
||||
'feature' is not an identifier
|
||||
|
||||
attr_rustc_allowed_unstable_pairing =
|
||||
attr_parsing_rustc_allowed_unstable_pairing =
|
||||
`rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute
|
||||
|
||||
attr_rustc_const_stable_indirect_pairing =
|
||||
attr_parsing_rustc_const_stable_indirect_pairing =
|
||||
`const_stable_indirect` attribute does not make sense on `rustc_const_stable` function, its behavior is already implied
|
||||
|
||||
attr_rustc_promotable_pairing =
|
||||
attr_parsing_rustc_promotable_pairing =
|
||||
`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute
|
||||
|
||||
attr_soft_no_args =
|
||||
attr_parsing_soft_no_args =
|
||||
`soft` should not have any arguments
|
||||
|
||||
attr_unknown_meta_item =
|
||||
attr_parsing_unknown_meta_item =
|
||||
unknown meta item '{$item}'
|
||||
.label = expected one of {$expected}
|
||||
|
||||
attr_unknown_version_literal =
|
||||
attr_parsing_unknown_version_literal =
|
||||
unknown version literal format, assuming it refers to a future version
|
||||
|
||||
attr_unstable_cfg_target_compact =
|
||||
attr_parsing_unstable_cfg_target_compact =
|
||||
compact `cfg(target(..))` is experimental and subject to change
|
||||
|
||||
attr_unsupported_literal_cfg_boolean =
|
||||
attr_parsing_unsupported_literal_cfg_boolean =
|
||||
literal in `cfg` predicate value must be a boolean
|
||||
attr_unsupported_literal_cfg_string =
|
||||
attr_parsing_unsupported_literal_cfg_string =
|
||||
literal in `cfg` predicate value must be a string
|
||||
attr_unsupported_literal_deprecated_kv_pair =
|
||||
attr_parsing_unsupported_literal_deprecated_kv_pair =
|
||||
item in `deprecated` must be a key/value pair
|
||||
attr_unsupported_literal_deprecated_string =
|
||||
attr_parsing_unsupported_literal_deprecated_string =
|
||||
literal in `deprecated` value must be a string
|
||||
attr_unsupported_literal_generic =
|
||||
attr_parsing_unsupported_literal_generic =
|
||||
unsupported literal
|
||||
attr_unsupported_literal_suggestion =
|
||||
attr_parsing_unsupported_literal_suggestion =
|
||||
consider removing the prefix
|
||||
49
compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs
Normal file
49
compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
use rustc_ast::attr::{AttributeExt, filter_by_name};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::{Symbol, sym};
|
||||
|
||||
use crate::session_diagnostics;
|
||||
|
||||
pub fn allow_internal_unstable<'a>(
|
||||
sess: &'a Session,
|
||||
attrs: &'a [impl AttributeExt],
|
||||
) -> impl Iterator<Item = Symbol> + 'a {
|
||||
allow_unstable(sess, attrs, sym::allow_internal_unstable)
|
||||
}
|
||||
|
||||
pub fn rustc_allow_const_fn_unstable<'a>(
|
||||
sess: &'a Session,
|
||||
attrs: &'a [impl AttributeExt],
|
||||
) -> impl Iterator<Item = Symbol> + 'a {
|
||||
allow_unstable(sess, attrs, sym::rustc_allow_const_fn_unstable)
|
||||
}
|
||||
|
||||
fn allow_unstable<'a>(
|
||||
sess: &'a Session,
|
||||
attrs: &'a [impl AttributeExt],
|
||||
symbol: Symbol,
|
||||
) -> impl Iterator<Item = Symbol> + 'a {
|
||||
let attrs = filter_by_name(attrs, symbol);
|
||||
let list = attrs
|
||||
.filter_map(move |attr| {
|
||||
attr.meta_item_list().or_else(|| {
|
||||
sess.dcx().emit_err(session_diagnostics::ExpectsFeatureList {
|
||||
span: attr.span(),
|
||||
name: symbol.to_ident_string(),
|
||||
});
|
||||
None
|
||||
})
|
||||
})
|
||||
.flatten();
|
||||
|
||||
list.into_iter().filter_map(move |it| {
|
||||
let name = it.ident().map(|ident| ident.name);
|
||||
if name.is_none() {
|
||||
sess.dcx().emit_err(session_diagnostics::ExpectsFeatures {
|
||||
span: it.span(),
|
||||
name: symbol.to_ident_string(),
|
||||
});
|
||||
}
|
||||
name
|
||||
})
|
||||
}
|
||||
253
compiler/rustc_attr_parsing/src/attributes/cfg.rs
Normal file
253
compiler/rustc_attr_parsing/src/attributes/cfg.rs
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
//! Parsing and validation of builtin attributes
|
||||
|
||||
use rustc_ast::{self as ast, LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, NodeId};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_attr_data_structures::RustcVersion;
|
||||
use rustc_feature::{Features, GatedCfg, find_gated_cfg};
|
||||
use rustc_session::Session;
|
||||
use rustc_session::config::ExpectedValues;
|
||||
use rustc_session::lint::BuiltinLintDiag;
|
||||
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::{Span, Symbol, kw, sym};
|
||||
|
||||
use crate::util::UnsupportedLiteralReason;
|
||||
use crate::{fluent_generated, parse_version, session_diagnostics};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Condition {
|
||||
pub name: Symbol,
|
||||
pub name_span: Span,
|
||||
pub value: Option<Symbol>,
|
||||
pub value_span: Option<Span>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
/// Tests if a cfg-pattern matches the cfg set
|
||||
pub fn cfg_matches(
|
||||
cfg: &ast::MetaItemInner,
|
||||
sess: &Session,
|
||||
lint_node_id: NodeId,
|
||||
features: Option<&Features>,
|
||||
) -> bool {
|
||||
eval_condition(cfg, sess, features, &mut |cfg| {
|
||||
try_gate_cfg(cfg.name, cfg.span, sess, features);
|
||||
match sess.psess.check_config.expecteds.get(&cfg.name) {
|
||||
Some(ExpectedValues::Some(values)) if !values.contains(&cfg.value) => {
|
||||
sess.psess.buffer_lint(
|
||||
UNEXPECTED_CFGS,
|
||||
cfg.span,
|
||||
lint_node_id,
|
||||
BuiltinLintDiag::UnexpectedCfgValue(
|
||||
(cfg.name, cfg.name_span),
|
||||
cfg.value.map(|v| (v, cfg.value_span.unwrap())),
|
||||
),
|
||||
);
|
||||
}
|
||||
None if sess.psess.check_config.exhaustive_names => {
|
||||
sess.psess.buffer_lint(
|
||||
UNEXPECTED_CFGS,
|
||||
cfg.span,
|
||||
lint_node_id,
|
||||
BuiltinLintDiag::UnexpectedCfgName(
|
||||
(cfg.name, cfg.name_span),
|
||||
cfg.value.map(|v| (v, cfg.value_span.unwrap())),
|
||||
),
|
||||
);
|
||||
}
|
||||
_ => { /* not unexpected */ }
|
||||
}
|
||||
sess.psess.config.contains(&(cfg.name, cfg.value))
|
||||
})
|
||||
}
|
||||
|
||||
fn try_gate_cfg(name: Symbol, span: Span, sess: &Session, features: Option<&Features>) {
|
||||
let gate = find_gated_cfg(|sym| sym == name);
|
||||
if let (Some(feats), Some(gated_cfg)) = (features, gate) {
|
||||
gate_cfg(gated_cfg, span, sess, feats);
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &Session, features: &Features) {
|
||||
let (cfg, feature, has_feature) = gated_cfg;
|
||||
if !has_feature(features) && !cfg_span.allows_unstable(*feature) {
|
||||
let explain = format!("`cfg({cfg})` is experimental and subject to change");
|
||||
feature_err(sess, *feature, cfg_span, explain).emit();
|
||||
}
|
||||
}
|
||||
|
||||
/// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to
|
||||
/// evaluate individual items.
|
||||
pub fn eval_condition(
|
||||
cfg: &ast::MetaItemInner,
|
||||
sess: &Session,
|
||||
features: Option<&Features>,
|
||||
eval: &mut impl FnMut(Condition) -> bool,
|
||||
) -> bool {
|
||||
let dcx = sess.dcx();
|
||||
|
||||
let cfg = match cfg {
|
||||
ast::MetaItemInner::MetaItem(meta_item) => meta_item,
|
||||
ast::MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => {
|
||||
if let Some(features) = features {
|
||||
// we can't use `try_gate_cfg` as symbols don't differentiate between `r#true`
|
||||
// and `true`, and we want to keep the former working without feature gate
|
||||
gate_cfg(
|
||||
&(
|
||||
if *b { kw::True } else { kw::False },
|
||||
sym::cfg_boolean_literals,
|
||||
|features: &Features| features.cfg_boolean_literals(),
|
||||
),
|
||||
cfg.span(),
|
||||
sess,
|
||||
features,
|
||||
);
|
||||
}
|
||||
return *b;
|
||||
}
|
||||
_ => {
|
||||
dcx.emit_err(session_diagnostics::UnsupportedLiteral {
|
||||
span: cfg.span(),
|
||||
reason: UnsupportedLiteralReason::CfgBoolean,
|
||||
is_bytestr: false,
|
||||
start_point_span: sess.source_map().start_point(cfg.span()),
|
||||
});
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
match &cfg.kind {
|
||||
ast::MetaItemKind::List(mis) if cfg.name_or_empty() == sym::version => {
|
||||
try_gate_cfg(sym::version, cfg.span, sess, features);
|
||||
let (min_version, span) = match &mis[..] {
|
||||
[MetaItemInner::Lit(MetaItemLit { kind: LitKind::Str(sym, ..), span, .. })] => {
|
||||
(sym, span)
|
||||
}
|
||||
[
|
||||
MetaItemInner::Lit(MetaItemLit { span, .. })
|
||||
| MetaItemInner::MetaItem(MetaItem { span, .. }),
|
||||
] => {
|
||||
dcx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: *span });
|
||||
return false;
|
||||
}
|
||||
[..] => {
|
||||
dcx.emit_err(session_diagnostics::ExpectedSingleVersionLiteral {
|
||||
span: cfg.span,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
};
|
||||
let Some(min_version) = parse_version(*min_version) else {
|
||||
dcx.emit_warn(session_diagnostics::UnknownVersionLiteral { span: *span });
|
||||
return false;
|
||||
};
|
||||
|
||||
// See https://github.com/rust-lang/rust/issues/64796#issuecomment-640851454 for details
|
||||
if sess.psess.assume_incomplete_release {
|
||||
RustcVersion::CURRENT > min_version
|
||||
} else {
|
||||
RustcVersion::CURRENT >= min_version
|
||||
}
|
||||
}
|
||||
ast::MetaItemKind::List(mis) => {
|
||||
for mi in mis.iter() {
|
||||
if mi.meta_item_or_bool().is_none() {
|
||||
dcx.emit_err(session_diagnostics::UnsupportedLiteral {
|
||||
span: mi.span(),
|
||||
reason: UnsupportedLiteralReason::Generic,
|
||||
is_bytestr: false,
|
||||
start_point_span: sess.source_map().start_point(mi.span()),
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// The unwraps below may look dangerous, but we've already asserted
|
||||
// that they won't fail with the loop above.
|
||||
match cfg.name_or_empty() {
|
||||
sym::any => mis
|
||||
.iter()
|
||||
// We don't use any() here, because we want to evaluate all cfg condition
|
||||
// as eval_condition can (and does) extra checks
|
||||
.fold(false, |res, mi| res | eval_condition(mi, sess, features, eval)),
|
||||
sym::all => mis
|
||||
.iter()
|
||||
// We don't use all() here, because we want to evaluate all cfg condition
|
||||
// as eval_condition can (and does) extra checks
|
||||
.fold(true, |res, mi| res & eval_condition(mi, sess, features, eval)),
|
||||
sym::not => {
|
||||
let [mi] = mis.as_slice() else {
|
||||
dcx.emit_err(session_diagnostics::ExpectedOneCfgPattern { span: cfg.span });
|
||||
return false;
|
||||
};
|
||||
|
||||
!eval_condition(mi, sess, features, eval)
|
||||
}
|
||||
sym::target => {
|
||||
if let Some(features) = features
|
||||
&& !features.cfg_target_compact()
|
||||
{
|
||||
feature_err(
|
||||
sess,
|
||||
sym::cfg_target_compact,
|
||||
cfg.span,
|
||||
fluent_generated::attr_parsing_unstable_cfg_target_compact,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
mis.iter().fold(true, |res, mi| {
|
||||
let Some(mut mi) = mi.meta_item().cloned() else {
|
||||
dcx.emit_err(session_diagnostics::CfgPredicateIdentifier {
|
||||
span: mi.span(),
|
||||
});
|
||||
return false;
|
||||
};
|
||||
|
||||
if let [seg, ..] = &mut mi.path.segments[..] {
|
||||
seg.ident.name = Symbol::intern(&format!("target_{}", seg.ident.name));
|
||||
}
|
||||
|
||||
res & eval_condition(
|
||||
&ast::MetaItemInner::MetaItem(mi),
|
||||
sess,
|
||||
features,
|
||||
eval,
|
||||
)
|
||||
})
|
||||
}
|
||||
_ => {
|
||||
dcx.emit_err(session_diagnostics::InvalidPredicate {
|
||||
span: cfg.span,
|
||||
predicate: pprust::path_to_string(&cfg.path),
|
||||
});
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::MetaItemKind::Word | MetaItemKind::NameValue(..) if cfg.path.segments.len() != 1 => {
|
||||
dcx.emit_err(session_diagnostics::CfgPredicateIdentifier { span: cfg.path.span });
|
||||
true
|
||||
}
|
||||
MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
|
||||
dcx.emit_err(session_diagnostics::UnsupportedLiteral {
|
||||
span: lit.span,
|
||||
reason: UnsupportedLiteralReason::CfgString,
|
||||
is_bytestr: lit.kind.is_bytestr(),
|
||||
start_point_span: sess.source_map().start_point(lit.span),
|
||||
});
|
||||
true
|
||||
}
|
||||
ast::MetaItemKind::Word | ast::MetaItemKind::NameValue(..) => {
|
||||
let ident = cfg.ident().expect("multi-segment cfg predicate");
|
||||
eval(Condition {
|
||||
name: ident.name,
|
||||
name_span: ident.span,
|
||||
value: cfg.value_str(),
|
||||
value_span: cfg.name_value_literal_span(),
|
||||
span: cfg.span,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
21
compiler/rustc_attr_parsing/src/attributes/confusables.rs
Normal file
21
compiler/rustc_attr_parsing/src/attributes/confusables.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
//! Parsing and validation of builtin attributes
|
||||
|
||||
use rustc_ast::MetaItemInner;
|
||||
use rustc_ast::attr::AttributeExt;
|
||||
use rustc_span::Symbol;
|
||||
|
||||
/// Read the content of a `rustc_confusables` attribute, and return the list of candidate names.
|
||||
pub fn parse_confusables(attr: &impl AttributeExt) -> Option<Vec<Symbol>> {
|
||||
let metas = attr.meta_item_list()?;
|
||||
|
||||
let mut candidates = Vec::new();
|
||||
|
||||
for meta in metas {
|
||||
let MetaItemInner::Lit(meta_lit) = meta else {
|
||||
return None;
|
||||
};
|
||||
candidates.push(meta_lit.symbol);
|
||||
}
|
||||
|
||||
Some(candidates)
|
||||
}
|
||||
148
compiler/rustc_attr_parsing/src/attributes/deprecation.rs
Normal file
148
compiler/rustc_attr_parsing/src/attributes/deprecation.rs
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
//! Parsing and validation of builtin attributes
|
||||
|
||||
use rustc_ast::attr::AttributeExt;
|
||||
use rustc_ast::{MetaItem, MetaItemInner};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_attr_data_structures::{DeprecatedSince, Deprecation};
|
||||
use rustc_feature::Features;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
|
||||
use super::util::UnsupportedLiteralReason;
|
||||
use crate::{parse_version, session_diagnostics};
|
||||
|
||||
/// Finds the deprecation attribute. `None` if none exists.
|
||||
pub fn find_deprecation(
|
||||
sess: &Session,
|
||||
features: &Features,
|
||||
attrs: &[impl AttributeExt],
|
||||
) -> Option<(Deprecation, Span)> {
|
||||
let mut depr: Option<(Deprecation, Span)> = None;
|
||||
let is_rustc = features.staged_api();
|
||||
|
||||
'outer: for attr in attrs {
|
||||
if !attr.has_name(sym::deprecated) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut since = None;
|
||||
let mut note = None;
|
||||
let mut suggestion = None;
|
||||
|
||||
if attr.is_doc_comment() {
|
||||
continue;
|
||||
} else if attr.is_word() {
|
||||
} else if let Some(value) = attr.value_str() {
|
||||
note = Some(value)
|
||||
} else if let Some(list) = attr.meta_item_list() {
|
||||
let get = |meta: &MetaItem, item: &mut Option<Symbol>| {
|
||||
if item.is_some() {
|
||||
sess.dcx().emit_err(session_diagnostics::MultipleItem {
|
||||
span: meta.span,
|
||||
item: pprust::path_to_string(&meta.path),
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if let Some(v) = meta.value_str() {
|
||||
*item = Some(v);
|
||||
true
|
||||
} else {
|
||||
if let Some(lit) = meta.name_value_literal() {
|
||||
sess.dcx().emit_err(session_diagnostics::UnsupportedLiteral {
|
||||
span: lit.span,
|
||||
reason: UnsupportedLiteralReason::DeprecatedString,
|
||||
is_bytestr: lit.kind.is_bytestr(),
|
||||
start_point_span: sess.source_map().start_point(lit.span),
|
||||
});
|
||||
} else {
|
||||
sess.dcx()
|
||||
.emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span });
|
||||
}
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
for meta in &list {
|
||||
match meta {
|
||||
MetaItemInner::MetaItem(mi) => match mi.name_or_empty() {
|
||||
sym::since => {
|
||||
if !get(mi, &mut since) {
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
sym::note => {
|
||||
if !get(mi, &mut note) {
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
sym::suggestion => {
|
||||
if !features.deprecated_suggestion() {
|
||||
sess.dcx().emit_err(
|
||||
session_diagnostics::DeprecatedItemSuggestion {
|
||||
span: mi.span,
|
||||
is_nightly: sess.is_nightly_build(),
|
||||
details: (),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if !get(mi, &mut suggestion) {
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
sess.dcx().emit_err(session_diagnostics::UnknownMetaItem {
|
||||
span: meta.span(),
|
||||
item: pprust::path_to_string(&mi.path),
|
||||
expected: if features.deprecated_suggestion() {
|
||||
&["since", "note", "suggestion"]
|
||||
} else {
|
||||
&["since", "note"]
|
||||
},
|
||||
});
|
||||
continue 'outer;
|
||||
}
|
||||
},
|
||||
MetaItemInner::Lit(lit) => {
|
||||
sess.dcx().emit_err(session_diagnostics::UnsupportedLiteral {
|
||||
span: lit.span,
|
||||
reason: UnsupportedLiteralReason::DeprecatedKvPair,
|
||||
is_bytestr: false,
|
||||
start_point_span: sess.source_map().start_point(lit.span),
|
||||
});
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
let since = if let Some(since) = since {
|
||||
if since.as_str() == "TBD" {
|
||||
DeprecatedSince::Future
|
||||
} else if !is_rustc {
|
||||
DeprecatedSince::NonStandard(since)
|
||||
} else if let Some(version) = parse_version(since) {
|
||||
DeprecatedSince::RustcVersion(version)
|
||||
} else {
|
||||
sess.dcx().emit_err(session_diagnostics::InvalidSince { span: attr.span() });
|
||||
DeprecatedSince::Err
|
||||
}
|
||||
} else if is_rustc {
|
||||
sess.dcx().emit_err(session_diagnostics::MissingSince { span: attr.span() });
|
||||
DeprecatedSince::Err
|
||||
} else {
|
||||
DeprecatedSince::Unspecified
|
||||
};
|
||||
|
||||
if is_rustc && note.is_none() {
|
||||
sess.dcx().emit_err(session_diagnostics::MissingNote { span: attr.span() });
|
||||
continue;
|
||||
}
|
||||
|
||||
depr = Some((Deprecation { since, note, suggestion }, attr.span()));
|
||||
}
|
||||
|
||||
depr
|
||||
}
|
||||
17
compiler/rustc_attr_parsing/src/attributes/mod.rs
Normal file
17
compiler/rustc_attr_parsing/src/attributes/mod.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
mod allow_unstable;
|
||||
mod cfg;
|
||||
mod confusables;
|
||||
mod deprecation;
|
||||
mod repr;
|
||||
mod stability;
|
||||
mod transparency;
|
||||
|
||||
pub mod util;
|
||||
|
||||
pub use allow_unstable::*;
|
||||
pub use cfg::*;
|
||||
pub use confusables::*;
|
||||
pub use deprecation::*;
|
||||
pub use repr::*;
|
||||
pub use stability::*;
|
||||
pub use transparency::*;
|
||||
215
compiler/rustc_attr_parsing/src/attributes/repr.rs
Normal file
215
compiler/rustc_attr_parsing/src/attributes/repr.rs
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
//! Parsing and validation of builtin attributes
|
||||
|
||||
use rustc_abi::Align;
|
||||
use rustc_ast::attr::AttributeExt;
|
||||
use rustc_ast::{self as ast, MetaItemKind};
|
||||
use rustc_attr_data_structures::IntType;
|
||||
use rustc_attr_data_structures::ReprAttr::*;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::{Symbol, sym};
|
||||
|
||||
use crate::ReprAttr;
|
||||
use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
|
||||
|
||||
/// Parse #[repr(...)] forms.
|
||||
///
|
||||
/// Valid repr contents: any of the primitive integral type names (see
|
||||
/// `int_type_of_word`, below) to specify enum discriminant type; `C`, to use
|
||||
/// the same discriminant size that the corresponding C enum would or C
|
||||
/// structure layout, `packed` to remove padding, and `transparent` to delegate representation
|
||||
/// concerns to the only non-ZST field.
|
||||
pub fn find_repr_attrs(sess: &Session, attr: &impl AttributeExt) -> Vec<ReprAttr> {
|
||||
if attr.has_name(sym::repr) { parse_repr_attr(sess, attr) } else { Vec::new() }
|
||||
}
|
||||
|
||||
pub fn parse_repr_attr(sess: &Session, attr: &impl AttributeExt) -> Vec<ReprAttr> {
|
||||
assert!(attr.has_name(sym::repr), "expected `#[repr(..)]`, found: {attr:?}");
|
||||
let mut acc = Vec::new();
|
||||
let dcx = sess.dcx();
|
||||
|
||||
if let Some(items) = attr.meta_item_list() {
|
||||
for item in items {
|
||||
let mut recognised = false;
|
||||
if item.is_word() {
|
||||
let hint = match item.name_or_empty() {
|
||||
sym::Rust => Some(ReprRust),
|
||||
sym::C => Some(ReprC),
|
||||
sym::packed => Some(ReprPacked(Align::ONE)),
|
||||
sym::simd => Some(ReprSimd),
|
||||
sym::transparent => Some(ReprTransparent),
|
||||
sym::align => {
|
||||
sess.dcx().emit_err(session_diagnostics::InvalidReprAlignNeedArg {
|
||||
span: item.span(),
|
||||
});
|
||||
recognised = true;
|
||||
None
|
||||
}
|
||||
name => int_type_of_word(name).map(ReprInt),
|
||||
};
|
||||
|
||||
if let Some(h) = hint {
|
||||
recognised = true;
|
||||
acc.push(h);
|
||||
}
|
||||
} else if let Some((name, value)) = item.singleton_lit_list() {
|
||||
let mut literal_error = None;
|
||||
let mut err_span = item.span();
|
||||
if name == sym::align {
|
||||
recognised = true;
|
||||
match parse_alignment(&value.kind) {
|
||||
Ok(literal) => acc.push(ReprAlign(literal)),
|
||||
Err(message) => {
|
||||
err_span = value.span;
|
||||
literal_error = Some(message)
|
||||
}
|
||||
};
|
||||
} else if name == sym::packed {
|
||||
recognised = true;
|
||||
match parse_alignment(&value.kind) {
|
||||
Ok(literal) => acc.push(ReprPacked(literal)),
|
||||
Err(message) => {
|
||||
err_span = value.span;
|
||||
literal_error = Some(message)
|
||||
}
|
||||
};
|
||||
} else if matches!(name, sym::Rust | sym::C | sym::simd | sym::transparent)
|
||||
|| int_type_of_word(name).is_some()
|
||||
{
|
||||
recognised = true;
|
||||
sess.dcx().emit_err(session_diagnostics::InvalidReprHintNoParen {
|
||||
span: item.span(),
|
||||
name: name.to_ident_string(),
|
||||
});
|
||||
}
|
||||
if let Some(literal_error) = literal_error {
|
||||
sess.dcx().emit_err(session_diagnostics::InvalidReprGeneric {
|
||||
span: err_span,
|
||||
repr_arg: name.to_ident_string(),
|
||||
error_part: literal_error,
|
||||
});
|
||||
}
|
||||
} else if let Some(meta_item) = item.meta_item() {
|
||||
match &meta_item.kind {
|
||||
MetaItemKind::NameValue(value) => {
|
||||
if meta_item.has_name(sym::align) || meta_item.has_name(sym::packed) {
|
||||
let name = meta_item.name_or_empty().to_ident_string();
|
||||
recognised = true;
|
||||
sess.dcx().emit_err(session_diagnostics::IncorrectReprFormatGeneric {
|
||||
span: item.span(),
|
||||
repr_arg: &name,
|
||||
cause: IncorrectReprFormatGenericCause::from_lit_kind(
|
||||
item.span(),
|
||||
&value.kind,
|
||||
&name,
|
||||
),
|
||||
});
|
||||
} else if matches!(
|
||||
meta_item.name_or_empty(),
|
||||
sym::Rust | sym::C | sym::simd | sym::transparent
|
||||
) || int_type_of_word(meta_item.name_or_empty()).is_some()
|
||||
{
|
||||
recognised = true;
|
||||
sess.dcx().emit_err(session_diagnostics::InvalidReprHintNoValue {
|
||||
span: meta_item.span,
|
||||
name: meta_item.name_or_empty().to_ident_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
MetaItemKind::List(nested_items) => {
|
||||
if meta_item.has_name(sym::align) {
|
||||
recognised = true;
|
||||
if let [nested_item] = nested_items.as_slice() {
|
||||
sess.dcx().emit_err(
|
||||
session_diagnostics::IncorrectReprFormatExpectInteger {
|
||||
span: nested_item.span(),
|
||||
},
|
||||
);
|
||||
} else {
|
||||
sess.dcx().emit_err(
|
||||
session_diagnostics::IncorrectReprFormatAlignOneArg {
|
||||
span: meta_item.span,
|
||||
},
|
||||
);
|
||||
}
|
||||
} else if meta_item.has_name(sym::packed) {
|
||||
recognised = true;
|
||||
if let [nested_item] = nested_items.as_slice() {
|
||||
sess.dcx().emit_err(
|
||||
session_diagnostics::IncorrectReprFormatPackedExpectInteger {
|
||||
span: nested_item.span(),
|
||||
},
|
||||
);
|
||||
} else {
|
||||
sess.dcx().emit_err(
|
||||
session_diagnostics::IncorrectReprFormatPackedOneOrZeroArg {
|
||||
span: meta_item.span,
|
||||
},
|
||||
);
|
||||
}
|
||||
} else if matches!(
|
||||
meta_item.name_or_empty(),
|
||||
sym::Rust | sym::C | sym::simd | sym::transparent
|
||||
) || int_type_of_word(meta_item.name_or_empty()).is_some()
|
||||
{
|
||||
recognised = true;
|
||||
sess.dcx().emit_err(session_diagnostics::InvalidReprHintNoParen {
|
||||
span: meta_item.span,
|
||||
name: meta_item.name_or_empty().to_ident_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
if !recognised {
|
||||
// Not a word we recognize. This will be caught and reported by
|
||||
// the `check_mod_attrs` pass, but this pass doesn't always run
|
||||
// (e.g. if we only pretty-print the source), so we have to gate
|
||||
// the `span_delayed_bug` call as follows:
|
||||
if sess.opts.pretty.map_or(true, |pp| pp.needs_analysis()) {
|
||||
dcx.span_delayed_bug(item.span(), "unrecognized representation hint");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
acc
|
||||
}
|
||||
|
||||
fn int_type_of_word(s: Symbol) -> Option<IntType> {
|
||||
use rustc_attr_data_structures::IntType::*;
|
||||
|
||||
match s {
|
||||
sym::i8 => Some(SignedInt(ast::IntTy::I8)),
|
||||
sym::u8 => Some(UnsignedInt(ast::UintTy::U8)),
|
||||
sym::i16 => Some(SignedInt(ast::IntTy::I16)),
|
||||
sym::u16 => Some(UnsignedInt(ast::UintTy::U16)),
|
||||
sym::i32 => Some(SignedInt(ast::IntTy::I32)),
|
||||
sym::u32 => Some(UnsignedInt(ast::UintTy::U32)),
|
||||
sym::i64 => Some(SignedInt(ast::IntTy::I64)),
|
||||
sym::u64 => Some(UnsignedInt(ast::UintTy::U64)),
|
||||
sym::i128 => Some(SignedInt(ast::IntTy::I128)),
|
||||
sym::u128 => Some(UnsignedInt(ast::UintTy::U128)),
|
||||
sym::isize => Some(SignedInt(ast::IntTy::Isize)),
|
||||
sym::usize => Some(UnsignedInt(ast::UintTy::Usize)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_alignment(node: &ast::LitKind) -> Result<Align, &'static str> {
|
||||
if let ast::LitKind::Int(literal, ast::LitIntType::Unsuffixed) = node {
|
||||
// `Align::from_bytes` accepts 0 as an input, check is_power_of_two() first
|
||||
if literal.get().is_power_of_two() {
|
||||
// Only possible error is larger than 2^29
|
||||
literal
|
||||
.get()
|
||||
.try_into()
|
||||
.ok()
|
||||
.and_then(|v| Align::from_bytes(v).ok())
|
||||
.ok_or("larger than 2^29")
|
||||
} else {
|
||||
Err("not a power of two")
|
||||
}
|
||||
} else {
|
||||
Err("not an unsuffixed integer")
|
||||
}
|
||||
}
|
||||
384
compiler/rustc_attr_parsing/src/attributes/stability.rs
Normal file
384
compiler/rustc_attr_parsing/src/attributes/stability.rs
Normal file
|
|
@ -0,0 +1,384 @@
|
|||
//! Parsing and validation of builtin attributes
|
||||
|
||||
use std::num::NonZero;
|
||||
|
||||
use rustc_ast::MetaItem;
|
||||
use rustc_ast::attr::AttributeExt;
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_attr_data_structures::{
|
||||
ConstStability, DefaultBodyStability, Stability, StabilityLevel, StableSince, UnstableReason,
|
||||
VERSION_PLACEHOLDER,
|
||||
};
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
|
||||
use crate::attributes::util::UnsupportedLiteralReason;
|
||||
use crate::{parse_version, session_diagnostics};
|
||||
|
||||
/// Collects stability info from `stable`/`unstable`/`rustc_allowed_through_unstable_modules`
|
||||
/// attributes in `attrs`. Returns `None` if no stability attributes are found.
|
||||
pub fn find_stability(
|
||||
sess: &Session,
|
||||
attrs: &[impl AttributeExt],
|
||||
item_sp: Span,
|
||||
) -> Option<(Stability, Span)> {
|
||||
let mut stab: Option<(Stability, Span)> = None;
|
||||
let mut allowed_through_unstable_modules = false;
|
||||
|
||||
for attr in attrs {
|
||||
match attr.name_or_empty() {
|
||||
sym::rustc_allowed_through_unstable_modules => allowed_through_unstable_modules = true,
|
||||
sym::unstable => {
|
||||
if stab.is_some() {
|
||||
sess.dcx().emit_err(session_diagnostics::MultipleStabilityLevels {
|
||||
span: attr.span(),
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
if let Some((feature, level)) = parse_unstability(sess, attr) {
|
||||
stab = Some((Stability { level, feature }, attr.span()));
|
||||
}
|
||||
}
|
||||
sym::stable => {
|
||||
if stab.is_some() {
|
||||
sess.dcx().emit_err(session_diagnostics::MultipleStabilityLevels {
|
||||
span: attr.span(),
|
||||
});
|
||||
break;
|
||||
}
|
||||
if let Some((feature, level)) = parse_stability(sess, attr) {
|
||||
stab = Some((Stability { level, feature }, attr.span()));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if allowed_through_unstable_modules {
|
||||
match &mut stab {
|
||||
Some((
|
||||
Stability {
|
||||
level: StabilityLevel::Stable { allowed_through_unstable_modules, .. },
|
||||
..
|
||||
},
|
||||
_,
|
||||
)) => *allowed_through_unstable_modules = true,
|
||||
_ => {
|
||||
sess.dcx()
|
||||
.emit_err(session_diagnostics::RustcAllowedUnstablePairing { span: item_sp });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stab
|
||||
}
|
||||
|
||||
/// Collects stability info from `rustc_const_stable`/`rustc_const_unstable`/`rustc_promotable`
|
||||
/// attributes in `attrs`. Returns `None` if no stability attributes are found.
|
||||
pub fn find_const_stability(
|
||||
sess: &Session,
|
||||
attrs: &[impl AttributeExt],
|
||||
item_sp: Span,
|
||||
) -> Option<(ConstStability, Span)> {
|
||||
let mut const_stab: Option<(ConstStability, Span)> = None;
|
||||
let mut promotable = false;
|
||||
let mut const_stable_indirect = false;
|
||||
|
||||
for attr in attrs {
|
||||
match attr.name_or_empty() {
|
||||
sym::rustc_promotable => promotable = true,
|
||||
sym::rustc_const_stable_indirect => const_stable_indirect = true,
|
||||
sym::rustc_const_unstable => {
|
||||
if const_stab.is_some() {
|
||||
sess.dcx().emit_err(session_diagnostics::MultipleStabilityLevels {
|
||||
span: attr.span(),
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
if let Some((feature, level)) = parse_unstability(sess, attr) {
|
||||
const_stab = Some((
|
||||
ConstStability {
|
||||
level,
|
||||
feature,
|
||||
const_stable_indirect: false,
|
||||
promotable: false,
|
||||
},
|
||||
attr.span(),
|
||||
));
|
||||
}
|
||||
}
|
||||
sym::rustc_const_stable => {
|
||||
if const_stab.is_some() {
|
||||
sess.dcx().emit_err(session_diagnostics::MultipleStabilityLevels {
|
||||
span: attr.span(),
|
||||
});
|
||||
break;
|
||||
}
|
||||
if let Some((feature, level)) = parse_stability(sess, attr) {
|
||||
const_stab = Some((
|
||||
ConstStability {
|
||||
level,
|
||||
feature,
|
||||
const_stable_indirect: false,
|
||||
promotable: false,
|
||||
},
|
||||
attr.span(),
|
||||
));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge promotable and const_stable_indirect into stability info
|
||||
if promotable {
|
||||
match &mut const_stab {
|
||||
Some((stab, _)) => stab.promotable = promotable,
|
||||
_ => {
|
||||
_ = sess
|
||||
.dcx()
|
||||
.emit_err(session_diagnostics::RustcPromotablePairing { span: item_sp })
|
||||
}
|
||||
}
|
||||
}
|
||||
if const_stable_indirect {
|
||||
match &mut const_stab {
|
||||
Some((stab, _)) => {
|
||||
if stab.is_const_unstable() {
|
||||
stab.const_stable_indirect = true;
|
||||
} else {
|
||||
_ = sess.dcx().emit_err(session_diagnostics::RustcConstStableIndirectPairing {
|
||||
span: item_sp,
|
||||
})
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// This function has no const stability attribute, but has `const_stable_indirect`.
|
||||
// We ignore that; unmarked functions are subject to recursive const stability
|
||||
// checks by default so we do carry out the user's intent.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const_stab
|
||||
}
|
||||
|
||||
/// Calculates the const stability for a const function in a `-Zforce-unstable-if-unmarked` crate
|
||||
/// without the `staged_api` feature.
|
||||
pub fn unmarked_crate_const_stab(
|
||||
_sess: &Session,
|
||||
attrs: &[impl AttributeExt],
|
||||
regular_stab: Stability,
|
||||
) -> ConstStability {
|
||||
assert!(regular_stab.level.is_unstable());
|
||||
// The only attribute that matters here is `rustc_const_stable_indirect`.
|
||||
// We enforce recursive const stability rules for those functions.
|
||||
let const_stable_indirect =
|
||||
attrs.iter().any(|a| a.name_or_empty() == sym::rustc_const_stable_indirect);
|
||||
ConstStability {
|
||||
feature: regular_stab.feature,
|
||||
const_stable_indirect,
|
||||
promotable: false,
|
||||
level: regular_stab.level,
|
||||
}
|
||||
}
|
||||
|
||||
/// Collects stability info from `rustc_default_body_unstable` attributes in `attrs`.
|
||||
/// Returns `None` if no stability attributes are found.
|
||||
pub fn find_body_stability(
|
||||
sess: &Session,
|
||||
attrs: &[impl AttributeExt],
|
||||
) -> Option<(DefaultBodyStability, Span)> {
|
||||
let mut body_stab: Option<(DefaultBodyStability, Span)> = None;
|
||||
|
||||
for attr in attrs {
|
||||
if attr.has_name(sym::rustc_default_body_unstable) {
|
||||
if body_stab.is_some() {
|
||||
sess.dcx()
|
||||
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span() });
|
||||
break;
|
||||
}
|
||||
|
||||
if let Some((feature, level)) = parse_unstability(sess, attr) {
|
||||
body_stab = Some((DefaultBodyStability { level, feature }, attr.span()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body_stab
|
||||
}
|
||||
|
||||
fn insert_or_error(sess: &Session, meta: &MetaItem, item: &mut Option<Symbol>) -> Option<()> {
|
||||
if item.is_some() {
|
||||
sess.dcx().emit_err(session_diagnostics::MultipleItem {
|
||||
span: meta.span,
|
||||
item: pprust::path_to_string(&meta.path),
|
||||
});
|
||||
None
|
||||
} else if let Some(v) = meta.value_str() {
|
||||
*item = Some(v);
|
||||
Some(())
|
||||
} else {
|
||||
sess.dcx().emit_err(session_diagnostics::IncorrectMetaItem { span: meta.span });
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Read the content of a `stable`/`rustc_const_stable` attribute, and return the feature name and
|
||||
/// its stability information.
|
||||
fn parse_stability(sess: &Session, attr: &impl AttributeExt) -> Option<(Symbol, StabilityLevel)> {
|
||||
let metas = attr.meta_item_list()?;
|
||||
|
||||
let mut feature = None;
|
||||
let mut since = None;
|
||||
for meta in metas {
|
||||
let Some(mi) = meta.meta_item() else {
|
||||
sess.dcx().emit_err(session_diagnostics::UnsupportedLiteral {
|
||||
span: meta.span(),
|
||||
reason: UnsupportedLiteralReason::Generic,
|
||||
is_bytestr: false,
|
||||
start_point_span: sess.source_map().start_point(meta.span()),
|
||||
});
|
||||
return None;
|
||||
};
|
||||
|
||||
match mi.name_or_empty() {
|
||||
sym::feature => insert_or_error(sess, mi, &mut feature)?,
|
||||
sym::since => insert_or_error(sess, mi, &mut since)?,
|
||||
_ => {
|
||||
sess.dcx().emit_err(session_diagnostics::UnknownMetaItem {
|
||||
span: meta.span(),
|
||||
item: pprust::path_to_string(&mi.path),
|
||||
expected: &["feature", "since"],
|
||||
});
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let feature = match feature {
|
||||
Some(feature) if rustc_lexer::is_ident(feature.as_str()) => Ok(feature),
|
||||
Some(_bad_feature) => {
|
||||
Err(sess.dcx().emit_err(session_diagnostics::NonIdentFeature { span: attr.span() }))
|
||||
}
|
||||
None => Err(sess.dcx().emit_err(session_diagnostics::MissingFeature { span: attr.span() })),
|
||||
};
|
||||
|
||||
let since = if let Some(since) = since {
|
||||
if since.as_str() == VERSION_PLACEHOLDER {
|
||||
StableSince::Current
|
||||
} else if let Some(version) = parse_version(since) {
|
||||
StableSince::Version(version)
|
||||
} else {
|
||||
sess.dcx().emit_err(session_diagnostics::InvalidSince { span: attr.span() });
|
||||
StableSince::Err
|
||||
}
|
||||
} else {
|
||||
sess.dcx().emit_err(session_diagnostics::MissingSince { span: attr.span() });
|
||||
StableSince::Err
|
||||
};
|
||||
|
||||
match feature {
|
||||
Ok(feature) => {
|
||||
let level = StabilityLevel::Stable { since, allowed_through_unstable_modules: false };
|
||||
Some((feature, level))
|
||||
}
|
||||
Err(ErrorGuaranteed { .. }) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Read the content of a `unstable`/`rustc_const_unstable`/`rustc_default_body_unstable`
|
||||
/// attribute, and return the feature name and its stability information.
|
||||
fn parse_unstability(sess: &Session, attr: &impl AttributeExt) -> Option<(Symbol, StabilityLevel)> {
|
||||
let metas = attr.meta_item_list()?;
|
||||
|
||||
let mut feature = None;
|
||||
let mut reason = None;
|
||||
let mut issue = None;
|
||||
let mut issue_num = None;
|
||||
let mut is_soft = false;
|
||||
let mut implied_by = None;
|
||||
for meta in metas {
|
||||
let Some(mi) = meta.meta_item() else {
|
||||
sess.dcx().emit_err(session_diagnostics::UnsupportedLiteral {
|
||||
span: meta.span(),
|
||||
reason: UnsupportedLiteralReason::Generic,
|
||||
is_bytestr: false,
|
||||
start_point_span: sess.source_map().start_point(meta.span()),
|
||||
});
|
||||
return None;
|
||||
};
|
||||
|
||||
match mi.name_or_empty() {
|
||||
sym::feature => insert_or_error(sess, mi, &mut feature)?,
|
||||
sym::reason => insert_or_error(sess, mi, &mut reason)?,
|
||||
sym::issue => {
|
||||
insert_or_error(sess, mi, &mut issue)?;
|
||||
|
||||
// These unwraps are safe because `insert_or_error` ensures the meta item
|
||||
// is a name/value pair string literal.
|
||||
issue_num = match issue.unwrap().as_str() {
|
||||
"none" => None,
|
||||
issue => match issue.parse::<NonZero<u32>>() {
|
||||
Ok(num) => Some(num),
|
||||
Err(err) => {
|
||||
sess.dcx().emit_err(
|
||||
session_diagnostics::InvalidIssueString {
|
||||
span: mi.span,
|
||||
cause: session_diagnostics::InvalidIssueStringCause::from_int_error_kind(
|
||||
mi.name_value_literal_span().unwrap(),
|
||||
err.kind(),
|
||||
),
|
||||
},
|
||||
);
|
||||
return None;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
sym::soft => {
|
||||
if !mi.is_word() {
|
||||
sess.dcx().emit_err(session_diagnostics::SoftNoArgs { span: mi.span });
|
||||
}
|
||||
is_soft = true;
|
||||
}
|
||||
sym::implied_by => insert_or_error(sess, mi, &mut implied_by)?,
|
||||
_ => {
|
||||
sess.dcx().emit_err(session_diagnostics::UnknownMetaItem {
|
||||
span: meta.span(),
|
||||
item: pprust::path_to_string(&mi.path),
|
||||
expected: &["feature", "reason", "issue", "soft", "implied_by"],
|
||||
});
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let feature = match feature {
|
||||
Some(feature) if rustc_lexer::is_ident(feature.as_str()) => Ok(feature),
|
||||
Some(_bad_feature) => {
|
||||
Err(sess.dcx().emit_err(session_diagnostics::NonIdentFeature { span: attr.span() }))
|
||||
}
|
||||
None => Err(sess.dcx().emit_err(session_diagnostics::MissingFeature { span: attr.span() })),
|
||||
};
|
||||
|
||||
let issue = issue.ok_or_else(|| {
|
||||
sess.dcx().emit_err(session_diagnostics::MissingIssue { span: attr.span() })
|
||||
});
|
||||
|
||||
match (feature, issue) {
|
||||
(Ok(feature), Ok(_)) => {
|
||||
let level = StabilityLevel::Unstable {
|
||||
reason: UnstableReason::from_opt_reason(reason),
|
||||
issue: issue_num,
|
||||
is_soft,
|
||||
implied_by,
|
||||
};
|
||||
Some((feature, level))
|
||||
}
|
||||
(Err(ErrorGuaranteed { .. }), _) | (_, Err(ErrorGuaranteed { .. })) => None,
|
||||
}
|
||||
}
|
||||
36
compiler/rustc_attr_parsing/src/attributes/transparency.rs
Normal file
36
compiler/rustc_attr_parsing/src/attributes/transparency.rs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
use rustc_ast::attr::AttributeExt;
|
||||
use rustc_attr_data_structures::TransparencyError;
|
||||
use rustc_span::hygiene::Transparency;
|
||||
use rustc_span::sym;
|
||||
|
||||
pub fn find_transparency(
|
||||
attrs: &[impl AttributeExt],
|
||||
macro_rules: bool,
|
||||
) -> (Transparency, Option<TransparencyError>) {
|
||||
let mut transparency = None;
|
||||
let mut error = None;
|
||||
for attr in attrs {
|
||||
if attr.has_name(sym::rustc_macro_transparency) {
|
||||
if let Some((_, old_span)) = transparency {
|
||||
error = Some(TransparencyError::MultipleTransparencyAttrs(old_span, attr.span()));
|
||||
break;
|
||||
} else if let Some(value) = attr.value_str() {
|
||||
transparency = Some((
|
||||
match value {
|
||||
sym::transparent => Transparency::Transparent,
|
||||
sym::semitransparent => Transparency::SemiTransparent,
|
||||
sym::opaque => Transparency::Opaque,
|
||||
_ => {
|
||||
error =
|
||||
Some(TransparencyError::UnknownTransparency(value, attr.span()));
|
||||
continue;
|
||||
}
|
||||
},
|
||||
attr.span(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
let fallback = if macro_rules { Transparency::SemiTransparent } else { Transparency::Opaque };
|
||||
(transparency.map_or(fallback, |t| t.0), error)
|
||||
}
|
||||
36
compiler/rustc_attr_parsing/src/attributes/util.rs
Normal file
36
compiler/rustc_attr_parsing/src/attributes/util.rs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
use rustc_ast::attr::{AttributeExt, first_attr_value_str_by_name};
|
||||
use rustc_attr_data_structures::RustcVersion;
|
||||
use rustc_feature::is_builtin_attr_name;
|
||||
use rustc_span::{Symbol, sym};
|
||||
|
||||
pub(crate) enum UnsupportedLiteralReason {
|
||||
Generic,
|
||||
CfgString,
|
||||
CfgBoolean,
|
||||
DeprecatedString,
|
||||
DeprecatedKvPair,
|
||||
}
|
||||
|
||||
pub fn is_builtin_attr(attr: &impl AttributeExt) -> bool {
|
||||
attr.is_doc_comment() || attr.ident().is_some_and(|ident| is_builtin_attr_name(ident.name))
|
||||
}
|
||||
|
||||
pub fn find_crate_name(attrs: &[impl AttributeExt]) -> Option<Symbol> {
|
||||
first_attr_value_str_by_name(attrs, sym::crate_name)
|
||||
}
|
||||
|
||||
/// Parse a rustc version number written inside string literal in an attribute,
|
||||
/// like appears in `since = "1.0.0"`. Suffixes like "-dev" and "-nightly" are
|
||||
/// not accepted in this position, unlike when parsing CFG_RELEASE.
|
||||
pub fn parse_version(s: Symbol) -> Option<RustcVersion> {
|
||||
let mut components = s.as_str().split('-');
|
||||
let d = components.next()?;
|
||||
if components.next().is_some() {
|
||||
return None;
|
||||
}
|
||||
let mut digits = d.splitn(3, '.');
|
||||
let major = digits.next()?.parse().ok()?;
|
||||
let minor = digits.next()?.parse().ok()?;
|
||||
let patch = digits.next().unwrap_or("0").parse().ok()?;
|
||||
Some(RustcVersion { major, minor, patch })
|
||||
}
|
||||
|
|
@ -12,14 +12,11 @@
|
|||
#![warn(unreachable_pub)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
mod builtin;
|
||||
mod attributes;
|
||||
mod session_diagnostics;
|
||||
|
||||
pub use IntType::*;
|
||||
pub use ReprAttr::*;
|
||||
pub use StabilityLevel::*;
|
||||
pub use builtin::*;
|
||||
pub use rustc_ast::attr::*;
|
||||
pub(crate) use rustc_session::HashStableContext;
|
||||
pub use attributes::*;
|
||||
pub use rustc_attr_data_structures::*;
|
||||
pub use util::{find_crate_name, is_builtin_attr, parse_version};
|
||||
|
||||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
|
|
@ -6,17 +6,18 @@ use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, EmissionGuar
|
|||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::{Span, Symbol};
|
||||
|
||||
use crate::{UnsupportedLiteralReason, fluent_generated as fluent};
|
||||
use crate::attributes::util::UnsupportedLiteralReason;
|
||||
use crate::fluent_generated as fluent;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_expected_one_cfg_pattern, code = E0536)]
|
||||
#[diag(attr_parsing_expected_one_cfg_pattern, code = E0536)]
|
||||
pub(crate) struct ExpectedOneCfgPattern {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_invalid_predicate, code = E0537)]
|
||||
#[diag(attr_parsing_invalid_predicate, code = E0537)]
|
||||
pub(crate) struct InvalidPredicate {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -25,7 +26,7 @@ pub(crate) struct InvalidPredicate {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_multiple_item, code = E0538)]
|
||||
#[diag(attr_parsing_multiple_item, code = E0538)]
|
||||
pub(crate) struct MultipleItem {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -34,7 +35,7 @@ pub(crate) struct MultipleItem {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_incorrect_meta_item, code = E0539)]
|
||||
#[diag(attr_parsing_incorrect_meta_item, code = E0539)]
|
||||
pub(crate) struct IncorrectMetaItem {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -51,38 +52,38 @@ pub(crate) struct UnknownMetaItem<'a> {
|
|||
impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for UnknownMetaItem<'_> {
|
||||
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
|
||||
let expected = self.expected.iter().map(|name| format!("`{name}`")).collect::<Vec<_>>();
|
||||
Diag::new(dcx, level, fluent::attr_unknown_meta_item)
|
||||
Diag::new(dcx, level, fluent::attr_parsing_unknown_meta_item)
|
||||
.with_span(self.span)
|
||||
.with_code(E0541)
|
||||
.with_arg("item", self.item)
|
||||
.with_arg("expected", expected.join(", "))
|
||||
.with_span_label(self.span, fluent::attr_label)
|
||||
.with_span_label(self.span, fluent::attr_parsing_label)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_missing_since, code = E0542)]
|
||||
#[diag(attr_parsing_missing_since, code = E0542)]
|
||||
pub(crate) struct MissingSince {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_missing_note, code = E0543)]
|
||||
#[diag(attr_parsing_missing_note, code = E0543)]
|
||||
pub(crate) struct MissingNote {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_multiple_stability_levels, code = E0544)]
|
||||
#[diag(attr_parsing_multiple_stability_levels, code = E0544)]
|
||||
pub(crate) struct MultipleStabilityLevels {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_invalid_issue_string, code = E0545)]
|
||||
#[diag(attr_parsing_invalid_issue_string, code = E0545)]
|
||||
pub(crate) struct InvalidIssueString {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -95,31 +96,31 @@ pub(crate) struct InvalidIssueString {
|
|||
// translatable.
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum InvalidIssueStringCause {
|
||||
#[label(attr_must_not_be_zero)]
|
||||
#[label(attr_parsing_must_not_be_zero)]
|
||||
MustNotBeZero {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
|
||||
#[label(attr_empty)]
|
||||
#[label(attr_parsing_empty)]
|
||||
Empty {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
|
||||
#[label(attr_invalid_digit)]
|
||||
#[label(attr_parsing_invalid_digit)]
|
||||
InvalidDigit {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
|
||||
#[label(attr_pos_overflow)]
|
||||
#[label(attr_parsing_pos_overflow)]
|
||||
PosOverflow {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
|
||||
#[label(attr_neg_overflow)]
|
||||
#[label(attr_parsing_neg_overflow)]
|
||||
NegOverflow {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
|
|
@ -140,21 +141,21 @@ impl InvalidIssueStringCause {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_missing_feature, code = E0546)]
|
||||
#[diag(attr_parsing_missing_feature, code = E0546)]
|
||||
pub(crate) struct MissingFeature {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_non_ident_feature, code = E0546)]
|
||||
#[diag(attr_parsing_non_ident_feature, code = E0546)]
|
||||
pub(crate) struct NonIdentFeature {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_missing_issue, code = E0547)]
|
||||
#[diag(attr_parsing_missing_issue, code = E0547)]
|
||||
pub(crate) struct MissingIssue {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -163,20 +164,20 @@ pub(crate) struct MissingIssue {
|
|||
// FIXME: Why is this the same error code as `InvalidReprHintNoParen` and `InvalidReprHintNoValue`?
|
||||
// It is more similar to `IncorrectReprFormatGeneric`.
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_incorrect_repr_format_packed_one_or_zero_arg, code = E0552)]
|
||||
#[diag(attr_parsing_incorrect_repr_format_packed_one_or_zero_arg, code = E0552)]
|
||||
pub(crate) struct IncorrectReprFormatPackedOneOrZeroArg {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_incorrect_repr_format_packed_expect_integer, code = E0552)]
|
||||
#[diag(attr_parsing_incorrect_repr_format_packed_expect_integer, code = E0552)]
|
||||
pub(crate) struct IncorrectReprFormatPackedExpectInteger {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_invalid_repr_hint_no_paren, code = E0552)]
|
||||
#[diag(attr_parsing_invalid_repr_hint_no_paren, code = E0552)]
|
||||
pub(crate) struct InvalidReprHintNoParen {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -185,7 +186,7 @@ pub(crate) struct InvalidReprHintNoParen {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_invalid_repr_hint_no_value, code = E0552)]
|
||||
#[diag(attr_parsing_invalid_repr_hint_no_value, code = E0552)]
|
||||
pub(crate) struct InvalidReprHintNoValue {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -204,14 +205,18 @@ pub(crate) struct UnsupportedLiteral {
|
|||
impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for UnsupportedLiteral {
|
||||
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
|
||||
let mut diag = Diag::new(dcx, level, match self.reason {
|
||||
UnsupportedLiteralReason::Generic => fluent::attr_unsupported_literal_generic,
|
||||
UnsupportedLiteralReason::CfgString => fluent::attr_unsupported_literal_cfg_string,
|
||||
UnsupportedLiteralReason::CfgBoolean => fluent::attr_unsupported_literal_cfg_boolean,
|
||||
UnsupportedLiteralReason::Generic => fluent::attr_parsing_unsupported_literal_generic,
|
||||
UnsupportedLiteralReason::CfgString => {
|
||||
fluent::attr_parsing_unsupported_literal_cfg_string
|
||||
}
|
||||
UnsupportedLiteralReason::CfgBoolean => {
|
||||
fluent::attr_parsing_unsupported_literal_cfg_boolean
|
||||
}
|
||||
UnsupportedLiteralReason::DeprecatedString => {
|
||||
fluent::attr_unsupported_literal_deprecated_string
|
||||
fluent::attr_parsing_unsupported_literal_deprecated_string
|
||||
}
|
||||
UnsupportedLiteralReason::DeprecatedKvPair => {
|
||||
fluent::attr_unsupported_literal_deprecated_kv_pair
|
||||
fluent::attr_parsing_unsupported_literal_deprecated_kv_pair
|
||||
}
|
||||
});
|
||||
diag.span(self.span);
|
||||
|
|
@ -219,7 +224,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for UnsupportedLiteral {
|
|||
if self.is_bytestr {
|
||||
diag.span_suggestion(
|
||||
self.start_point_span,
|
||||
fluent::attr_unsupported_literal_suggestion,
|
||||
fluent::attr_parsing_unsupported_literal_suggestion,
|
||||
"",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
|
|
@ -229,7 +234,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for UnsupportedLiteral {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_invalid_repr_align_need_arg, code = E0589)]
|
||||
#[diag(attr_parsing_invalid_repr_align_need_arg, code = E0589)]
|
||||
pub(crate) struct InvalidReprAlignNeedArg {
|
||||
#[primary_span]
|
||||
#[suggestion(code = "align(...)", applicability = "has-placeholders")]
|
||||
|
|
@ -237,7 +242,7 @@ pub(crate) struct InvalidReprAlignNeedArg {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_invalid_repr_generic, code = E0589)]
|
||||
#[diag(attr_parsing_invalid_repr_generic, code = E0589)]
|
||||
pub(crate) struct InvalidReprGeneric<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -247,21 +252,21 @@ pub(crate) struct InvalidReprGeneric<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_incorrect_repr_format_align_one_arg, code = E0693)]
|
||||
#[diag(attr_parsing_incorrect_repr_format_align_one_arg, code = E0693)]
|
||||
pub(crate) struct IncorrectReprFormatAlignOneArg {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_incorrect_repr_format_expect_literal_integer, code = E0693)]
|
||||
#[diag(attr_parsing_incorrect_repr_format_expect_literal_integer, code = E0693)]
|
||||
pub(crate) struct IncorrectReprFormatExpectInteger {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_incorrect_repr_format_generic, code = E0693)]
|
||||
#[diag(attr_parsing_incorrect_repr_format_generic, code = E0693)]
|
||||
pub(crate) struct IncorrectReprFormatGeneric<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -274,7 +279,11 @@ pub(crate) struct IncorrectReprFormatGeneric<'a> {
|
|||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum IncorrectReprFormatGenericCause<'a> {
|
||||
#[suggestion(attr_suggestion, code = "{name}({int})", applicability = "machine-applicable")]
|
||||
#[suggestion(
|
||||
attr_parsing_suggestion,
|
||||
code = "{name}({int})",
|
||||
applicability = "machine-applicable"
|
||||
)]
|
||||
Int {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
|
|
@ -286,7 +295,11 @@ pub(crate) enum IncorrectReprFormatGenericCause<'a> {
|
|||
int: u128,
|
||||
},
|
||||
|
||||
#[suggestion(attr_suggestion, code = "{name}({symbol})", applicability = "machine-applicable")]
|
||||
#[suggestion(
|
||||
attr_parsing_suggestion,
|
||||
code = "{name}({symbol})",
|
||||
applicability = "machine-applicable"
|
||||
)]
|
||||
Symbol {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
|
|
@ -312,35 +325,35 @@ impl<'a> IncorrectReprFormatGenericCause<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_rustc_promotable_pairing, code = E0717)]
|
||||
#[diag(attr_parsing_rustc_promotable_pairing, code = E0717)]
|
||||
pub(crate) struct RustcPromotablePairing {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_rustc_const_stable_indirect_pairing)]
|
||||
#[diag(attr_parsing_rustc_const_stable_indirect_pairing)]
|
||||
pub(crate) struct RustcConstStableIndirectPairing {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_rustc_allowed_unstable_pairing, code = E0789)]
|
||||
#[diag(attr_parsing_rustc_allowed_unstable_pairing, code = E0789)]
|
||||
pub(crate) struct RustcAllowedUnstablePairing {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_cfg_predicate_identifier)]
|
||||
#[diag(attr_parsing_cfg_predicate_identifier)]
|
||||
pub(crate) struct CfgPredicateIdentifier {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_deprecated_item_suggestion)]
|
||||
#[diag(attr_parsing_deprecated_item_suggestion)]
|
||||
pub(crate) struct DeprecatedItemSuggestion {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -353,21 +366,21 @@ pub(crate) struct DeprecatedItemSuggestion {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_expected_single_version_literal)]
|
||||
#[diag(attr_parsing_expected_single_version_literal)]
|
||||
pub(crate) struct ExpectedSingleVersionLiteral {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_expected_version_literal)]
|
||||
#[diag(attr_parsing_expected_version_literal)]
|
||||
pub(crate) struct ExpectedVersionLiteral {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_expects_feature_list)]
|
||||
#[diag(attr_parsing_expects_feature_list)]
|
||||
pub(crate) struct ExpectsFeatureList {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -376,7 +389,7 @@ pub(crate) struct ExpectsFeatureList {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_expects_features)]
|
||||
#[diag(attr_parsing_expects_features)]
|
||||
pub(crate) struct ExpectsFeatures {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -385,21 +398,21 @@ pub(crate) struct ExpectsFeatures {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_invalid_since)]
|
||||
#[diag(attr_parsing_invalid_since)]
|
||||
pub(crate) struct InvalidSince {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_soft_no_args)]
|
||||
#[diag(attr_parsing_soft_no_args)]
|
||||
pub(crate) struct SoftNoArgs {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_unknown_version_literal)]
|
||||
#[diag(attr_parsing_unknown_version_literal)]
|
||||
pub(crate) struct UnknownVersionLiteral {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
|
@ -34,8 +34,7 @@ use rustc_middle::util::CallKind;
|
|||
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
|
||||
use rustc_span::def_id::{DefId, LocalDefId};
|
||||
use rustc_span::hygiene::DesugaringKind;
|
||||
use rustc_span::symbol::{Ident, kw, sym};
|
||||
use rustc_span::{BytePos, Span, Symbol};
|
||||
use rustc_span::{BytePos, Ident, Span, Symbol, kw, sym};
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
|
|
|
|||
|
|
@ -17,8 +17,7 @@ use rustc_middle::mir::{
|
|||
};
|
||||
use rustc_middle::ty::adjustment::PointerCoercion;
|
||||
use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt};
|
||||
use rustc_span::symbol::{Symbol, kw};
|
||||
use rustc_span::{DesugaringKind, Span, sym};
|
||||
use rustc_span::{DesugaringKind, Span, Symbol, kw, sym};
|
||||
use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,7 @@ use rustc_middle::util::{CallDesugaringKind, call_kind};
|
|||
use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{DUMMY_SP, Span, Symbol};
|
||||
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::{
|
||||
|
|
|
|||
|
|
@ -15,8 +15,7 @@ use rustc_middle::mir::{
|
|||
PlaceRef, ProjectionElem,
|
||||
};
|
||||
use rustc_middle::ty::{self, InstanceKind, Ty, TyCtxt, Upcast};
|
||||
use rustc_span::symbol::{Symbol, kw};
|
||||
use rustc_span::{BytePos, DesugaringKind, Span, sym};
|
||||
use rustc_span::{BytePos, DesugaringKind, Span, Symbol, kw, sym};
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits;
|
||||
|
|
@ -1474,16 +1473,27 @@ fn suggest_ampmut<'tcx>(
|
|||
// let x: &i32 = &'a 5;
|
||||
// ^^ lifetime annotation not allowed
|
||||
//
|
||||
if let Some(assignment_rhs_span) = opt_assignment_rhs_span
|
||||
&& let Ok(src) = tcx.sess.source_map().span_to_snippet(assignment_rhs_span)
|
||||
&& let Some(stripped) = src.strip_prefix('&')
|
||||
if let Some(rhs_span) = opt_assignment_rhs_span
|
||||
&& let Ok(rhs_str) = tcx.sess.source_map().span_to_snippet(rhs_span)
|
||||
&& let Some(rhs_str_no_amp) = rhs_str.strip_prefix('&')
|
||||
{
|
||||
let is_raw_ref = stripped.trim_start().starts_with("raw ");
|
||||
// We don't support raw refs yet
|
||||
if is_raw_ref {
|
||||
return None;
|
||||
// Suggest changing `&raw const` to `&raw mut` if applicable.
|
||||
if rhs_str_no_amp.trim_start().strip_prefix("raw const").is_some() {
|
||||
let const_idx = rhs_str.find("const").unwrap() as u32;
|
||||
let const_span = rhs_span
|
||||
.with_lo(rhs_span.lo() + BytePos(const_idx))
|
||||
.with_hi(rhs_span.lo() + BytePos(const_idx + "const".len() as u32));
|
||||
|
||||
return Some(AmpMutSugg {
|
||||
has_sugg: true,
|
||||
span: const_span,
|
||||
suggestion: "mut".to_owned(),
|
||||
additional: None,
|
||||
});
|
||||
}
|
||||
let is_mut = if let Some(rest) = stripped.trim_start().strip_prefix("mut") {
|
||||
|
||||
// Figure out if rhs already is `&mut`.
|
||||
let is_mut = if let Some(rest) = rhs_str_no_amp.trim_start().strip_prefix("mut") {
|
||||
match rest.chars().next() {
|
||||
// e.g. `&mut x`
|
||||
Some(c) if c.is_whitespace() => true,
|
||||
|
|
@ -1500,9 +1510,8 @@ fn suggest_ampmut<'tcx>(
|
|||
// if the reference is already mutable then there is nothing we can do
|
||||
// here.
|
||||
if !is_mut {
|
||||
let span = assignment_rhs_span;
|
||||
// shrink the span to just after the `&` in `&variable`
|
||||
let span = span.with_lo(span.lo() + BytePos(1)).shrink_to_lo();
|
||||
let span = rhs_span.with_lo(rhs_span.lo() + BytePos(1)).shrink_to_lo();
|
||||
|
||||
// FIXME(Ezrashaw): returning is bad because we still might want to
|
||||
// update the annotated type, see #106857.
|
||||
|
|
|
|||
|
|
@ -15,8 +15,7 @@ use rustc_middle::bug;
|
|||
use rustc_middle::hir::place::PlaceBase;
|
||||
use rustc_middle::mir::{ConstraintCategory, ReturnConstraint};
|
||||
use rustc_middle::ty::{self, GenericArgs, Region, RegionVid, Ty, TyCtxt, TypeVisitor};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::{Ident, kw};
|
||||
use rustc_span::{Ident, Span, kw};
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use rustc_trait_selection::error_reporting::infer::nice_region_error::{
|
||||
self, HirTraitObjectVisitor, NiceRegionError, TraitObjectVisitor, find_anon_type,
|
||||
|
|
@ -848,7 +847,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
return;
|
||||
};
|
||||
|
||||
let fn_returns = self.infcx.tcx.return_type_impl_or_dyn_traits(suitable_region.def_id);
|
||||
let fn_returns = self.infcx.tcx.return_type_impl_or_dyn_traits(suitable_region.scope);
|
||||
|
||||
let param = if let Some(param) =
|
||||
find_param_with_region(self.infcx.tcx, self.mir_def_id(), f, outlived_f)
|
||||
|
|
@ -875,7 +874,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
Some(arg),
|
||||
captures,
|
||||
Some((param.param_ty_span, param.param_ty.to_string())),
|
||||
Some(suitable_region.def_id),
|
||||
Some(suitable_region.scope),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
|
@ -883,7 +882,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
let Some((alias_tys, alias_span, lt_addition_span)) = self
|
||||
.infcx
|
||||
.tcx
|
||||
.return_type_impl_or_dyn_traits_with_type_alias(suitable_region.def_id)
|
||||
.return_type_impl_or_dyn_traits_with_type_alias(suitable_region.scope)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
|
@ -1018,18 +1017,20 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
return;
|
||||
};
|
||||
|
||||
let Some((ty_sub, _)) =
|
||||
self.infcx.tcx.is_suitable_region(self.mir_def_id(), sub).and_then(|anon_reg| {
|
||||
find_anon_type(self.infcx.tcx, self.mir_def_id(), sub, &anon_reg.bound_region)
|
||||
})
|
||||
let Some((ty_sub, _)) = self
|
||||
.infcx
|
||||
.tcx
|
||||
.is_suitable_region(self.mir_def_id(), sub)
|
||||
.and_then(|_| find_anon_type(self.infcx.tcx, self.mir_def_id(), sub))
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some((ty_sup, _)) =
|
||||
self.infcx.tcx.is_suitable_region(self.mir_def_id(), sup).and_then(|anon_reg| {
|
||||
find_anon_type(self.infcx.tcx, self.mir_def_id(), sup, &anon_reg.bound_region)
|
||||
})
|
||||
let Some((ty_sup, _)) = self
|
||||
.infcx
|
||||
.tcx
|
||||
.is_suitable_region(self.mir_def_id(), sup)
|
||||
.and_then(|_| find_anon_type(self.infcx.tcx, self.mir_def_id(), sup))
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@ use rustc_hir::def::{DefKind, Res};
|
|||
use rustc_middle::ty::print::RegionHighlightMode;
|
||||
use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, RegionVid, Ty};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::symbol::{Symbol, kw, sym};
|
||||
use rustc_span::{DUMMY_SP, Span};
|
||||
use rustc_span::{DUMMY_SP, Span, Symbol, kw, sym};
|
||||
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
|
|
@ -459,11 +458,8 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
|
|||
) -> RegionNameHighlight {
|
||||
let mut highlight = RegionHighlightMode::default();
|
||||
highlight.highlighting_region_vid(self.infcx.tcx, needle_fr, counter);
|
||||
let type_name = self
|
||||
.infcx
|
||||
.err_ctxt()
|
||||
.extract_inference_diagnostics_data(ty.into(), Some(highlight))
|
||||
.name;
|
||||
let type_name =
|
||||
self.infcx.err_ctxt().extract_inference_diagnostics_data(ty.into(), highlight).name;
|
||||
|
||||
debug!(
|
||||
"highlight_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}",
|
||||
|
|
@ -874,7 +870,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
|
|||
let type_name = self
|
||||
.infcx
|
||||
.err_ctxt()
|
||||
.extract_inference_diagnostics_data(yield_ty.into(), Some(highlight))
|
||||
.extract_inference_diagnostics_data(yield_ty.into(), highlight)
|
||||
.name;
|
||||
|
||||
let yield_span = match tcx.hir_node(self.mir_hir_id()) {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
use rustc_index::IndexSlice;
|
||||
use rustc_middle::mir::{Body, Local};
|
||||
use rustc_middle::ty::{self, RegionVid, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use tracing::debug;
|
||||
|
||||
use crate::region_infer::RegionInferenceContext;
|
||||
|
|
|
|||
|
|
@ -141,6 +141,9 @@ fn do_mir_borrowck<'tcx>(
|
|||
) -> (BorrowCheckResult<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
|
||||
let def = input_body.source.def_id().expect_local();
|
||||
let infcx = BorrowckInferCtxt::new(tcx, def);
|
||||
if let Some(e) = input_body.tainted_by_errors {
|
||||
infcx.set_tainted_by_errors(e);
|
||||
}
|
||||
|
||||
let mut local_names = IndexVec::from_elem(None, &input_body.local_decls);
|
||||
for var_debug_info in &input_body.var_debug_info {
|
||||
|
|
@ -162,13 +165,6 @@ fn do_mir_borrowck<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
let diags = &mut diags::BorrowckDiags::new();
|
||||
|
||||
// Gather the upvars of a closure, if any.
|
||||
if let Some(e) = input_body.tainted_by_errors {
|
||||
infcx.set_tainted_by_errors(e);
|
||||
}
|
||||
|
||||
// Replace all regions with fresh inference variables. This
|
||||
// requires first making our own copy of the MIR. This copy will
|
||||
// be modified (in place) to contain non-lexical lifetimes. It
|
||||
|
|
@ -224,6 +220,7 @@ fn do_mir_borrowck<'tcx>(
|
|||
|
||||
// We also have a `#[rustc_regions]` annotation that causes us to dump
|
||||
// information.
|
||||
let diags = &mut diags::BorrowckDiags::new();
|
||||
nll::dump_annotation(&infcx, body, ®ioncx, &opt_closure_req, &opaque_type_values, diags);
|
||||
|
||||
let movable_coroutine =
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
|
|||
use rustc_mir_dataflow::move_paths::MoveData;
|
||||
use rustc_mir_dataflow::points::DenseLocationMap;
|
||||
use rustc_session::config::MirIncludeSpans;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::sym;
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use crate::borrow_set::BorrowSet;
|
||||
|
|
@ -116,7 +116,7 @@ pub(crate) fn compute_regions<'a, 'tcx>(
|
|||
let var_origins = infcx.get_region_var_origins();
|
||||
|
||||
// If requested, emit legacy polonius facts.
|
||||
polonius::emit_facts(
|
||||
polonius::legacy::emit_facts(
|
||||
&mut all_facts,
|
||||
infcx.tcx,
|
||||
location_table,
|
||||
|
|
@ -124,6 +124,7 @@ pub(crate) fn compute_regions<'a, 'tcx>(
|
|||
borrow_set,
|
||||
move_data,
|
||||
&universal_region_relations,
|
||||
&constraints,
|
||||
);
|
||||
|
||||
let mut regioncx = RegionInferenceContext::new(
|
||||
|
|
|
|||
85
compiler/rustc_borrowck/src/polonius/legacy/accesses.rs
Normal file
85
compiler/rustc_borrowck/src/polonius/legacy/accesses.rs
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
|
||||
use rustc_middle::mir::{Body, Local, Location, Place};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_mir_dataflow::move_paths::{LookupResult, MoveData};
|
||||
use tracing::debug;
|
||||
|
||||
use crate::def_use::{self, DefUse};
|
||||
use crate::facts::AllFacts;
|
||||
use crate::location::{LocationIndex, LocationTable};
|
||||
use crate::universal_regions::UniversalRegions;
|
||||
|
||||
/// Emit polonius facts for variable defs, uses, drops, and path accesses.
|
||||
pub(crate) fn emit_access_facts<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
facts: &mut AllFacts,
|
||||
body: &Body<'tcx>,
|
||||
location_table: &LocationTable,
|
||||
move_data: &MoveData<'tcx>,
|
||||
universal_regions: &UniversalRegions<'tcx>,
|
||||
) {
|
||||
let mut extractor = AccessFactsExtractor { facts, move_data, location_table };
|
||||
extractor.visit_body(body);
|
||||
|
||||
for (local, local_decl) in body.local_decls.iter_enumerated() {
|
||||
debug!("add use_of_var_derefs_origin facts - local={:?}, type={:?}", local, local_decl.ty);
|
||||
tcx.for_each_free_region(&local_decl.ty, |region| {
|
||||
let region_vid = universal_regions.to_region_vid(region);
|
||||
facts.use_of_var_derefs_origin.push((local, region_vid.into()));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// MIR visitor extracting point-wise facts about accesses.
|
||||
struct AccessFactsExtractor<'a, 'tcx> {
|
||||
facts: &'a mut AllFacts,
|
||||
move_data: &'a MoveData<'tcx>,
|
||||
location_table: &'a LocationTable,
|
||||
}
|
||||
|
||||
impl<'tcx> AccessFactsExtractor<'_, 'tcx> {
|
||||
fn location_to_index(&self, location: Location) -> LocationIndex {
|
||||
self.location_table.mid_index(location)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Visitor<'tcx> for AccessFactsExtractor<'a, 'tcx> {
|
||||
fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) {
|
||||
match def_use::categorize(context) {
|
||||
Some(DefUse::Def) => {
|
||||
debug!("AccessFactsExtractor - emit def");
|
||||
self.facts.var_defined_at.push((local, self.location_to_index(location)));
|
||||
}
|
||||
Some(DefUse::Use) => {
|
||||
debug!("AccessFactsExtractor - emit use");
|
||||
self.facts.var_used_at.push((local, self.location_to_index(location)));
|
||||
}
|
||||
Some(DefUse::Drop) => {
|
||||
debug!("AccessFactsExtractor - emit drop");
|
||||
self.facts.var_dropped_at.push((local, self.location_to_index(location)));
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
|
||||
self.super_place(place, context, location);
|
||||
|
||||
match context {
|
||||
PlaceContext::NonMutatingUse(_)
|
||||
| PlaceContext::MutatingUse(MutatingUseContext::Borrow) => {
|
||||
let path = match self.move_data.rev_lookup.find(place.as_ref()) {
|
||||
LookupResult::Exact(path) | LookupResult::Parent(Some(path)) => path,
|
||||
_ => {
|
||||
// There's no path access to emit.
|
||||
return;
|
||||
}
|
||||
};
|
||||
debug!("AccessFactsExtractor - emit path access ({path:?}, {location:?})");
|
||||
self.facts.path_accessed_at_base.push((path, self.location_to_index(location)));
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -21,22 +21,22 @@ use crate::{
|
|||
/// Emit `loan_invalidated_at` facts.
|
||||
pub(super) fn emit_loan_invalidations<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
all_facts: &mut AllFacts,
|
||||
location_table: &LocationTable,
|
||||
facts: &mut AllFacts,
|
||||
body: &Body<'tcx>,
|
||||
location_table: &LocationTable,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
) {
|
||||
let dominators = body.basic_blocks.dominators();
|
||||
let mut visitor =
|
||||
LoanInvalidationsGenerator { all_facts, borrow_set, tcx, location_table, body, dominators };
|
||||
LoanInvalidationsGenerator { facts, borrow_set, tcx, location_table, body, dominators };
|
||||
visitor.visit_body(body);
|
||||
}
|
||||
|
||||
struct LoanInvalidationsGenerator<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
all_facts: &'a mut AllFacts,
|
||||
location_table: &'a LocationTable,
|
||||
facts: &'a mut AllFacts,
|
||||
body: &'a Body<'tcx>,
|
||||
location_table: &'a LocationTable,
|
||||
dominators: &'a Dominators<BasicBlock>,
|
||||
borrow_set: &'a BorrowSet<'tcx>,
|
||||
}
|
||||
|
|
@ -151,7 +151,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'a, 'tcx> {
|
|||
let resume = self.location_table.start_index(resume.start_location());
|
||||
for (i, data) in borrow_set.iter_enumerated() {
|
||||
if borrow_of_local_data(data.borrowed_place) {
|
||||
self.all_facts.loan_invalidated_at.push((resume, i));
|
||||
self.facts.loan_invalidated_at.push((resume, i));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -165,7 +165,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'a, 'tcx> {
|
|||
let start = self.location_table.start_index(location);
|
||||
for (i, data) in borrow_set.iter_enumerated() {
|
||||
if borrow_of_local_data(data.borrowed_place) {
|
||||
self.all_facts.loan_invalidated_at.push((start, i));
|
||||
self.facts.loan_invalidated_at.push((start, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -409,7 +409,7 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> {
|
|||
/// Generates a new `loan_invalidated_at(L, B)` fact.
|
||||
fn emit_loan_invalidated_at(&mut self, b: BorrowIndex, l: Location) {
|
||||
let lidx = self.location_table.start_index(l);
|
||||
self.all_facts.loan_invalidated_at.push((lidx, b));
|
||||
self.facts.loan_invalidated_at.push((lidx, b));
|
||||
}
|
||||
|
||||
fn check_activations(&mut self, location: Location) {
|
||||
|
|
@ -14,12 +14,12 @@ use crate::places_conflict;
|
|||
/// Emit `loan_killed_at` and `cfg_edge` facts at the same time.
|
||||
pub(super) fn emit_loan_kills<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
all_facts: &mut AllFacts,
|
||||
location_table: &LocationTable,
|
||||
facts: &mut AllFacts,
|
||||
body: &Body<'tcx>,
|
||||
location_table: &LocationTable,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
) {
|
||||
let mut visitor = LoanKillsGenerator { borrow_set, tcx, location_table, all_facts, body };
|
||||
let mut visitor = LoanKillsGenerator { borrow_set, tcx, location_table, facts, body };
|
||||
for (bb, data) in body.basic_blocks.iter_enumerated() {
|
||||
visitor.visit_basic_block_data(bb, data);
|
||||
}
|
||||
|
|
@ -27,7 +27,7 @@ pub(super) fn emit_loan_kills<'tcx>(
|
|||
|
||||
struct LoanKillsGenerator<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
all_facts: &'a mut AllFacts,
|
||||
facts: &'a mut AllFacts,
|
||||
location_table: &'a LocationTable,
|
||||
borrow_set: &'a BorrowSet<'tcx>,
|
||||
body: &'a Body<'tcx>,
|
||||
|
|
@ -36,12 +36,12 @@ struct LoanKillsGenerator<'a, 'tcx> {
|
|||
impl<'a, 'tcx> Visitor<'tcx> for LoanKillsGenerator<'a, 'tcx> {
|
||||
fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
|
||||
// Also record CFG facts here.
|
||||
self.all_facts.cfg_edge.push((
|
||||
self.facts.cfg_edge.push((
|
||||
self.location_table.start_index(location),
|
||||
self.location_table.mid_index(location),
|
||||
));
|
||||
|
||||
self.all_facts.cfg_edge.push((
|
||||
self.facts.cfg_edge.push((
|
||||
self.location_table.mid_index(location),
|
||||
self.location_table.start_index(location.successor_within_block()),
|
||||
));
|
||||
|
|
@ -63,15 +63,15 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanKillsGenerator<'a, 'tcx> {
|
|||
|
||||
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
|
||||
// Also record CFG facts here.
|
||||
self.all_facts.cfg_edge.push((
|
||||
self.facts.cfg_edge.push((
|
||||
self.location_table.start_index(location),
|
||||
self.location_table.mid_index(location),
|
||||
));
|
||||
|
||||
let successor_blocks = terminator.successors();
|
||||
self.all_facts.cfg_edge.reserve(successor_blocks.size_hint().0);
|
||||
self.facts.cfg_edge.reserve(successor_blocks.size_hint().0);
|
||||
for successor_block in successor_blocks {
|
||||
self.all_facts.cfg_edge.push((
|
||||
self.facts.cfg_edge.push((
|
||||
self.location_table.mid_index(location),
|
||||
self.location_table.start_index(successor_block.start_location()),
|
||||
));
|
||||
|
|
@ -128,7 +128,7 @@ impl<'tcx> LoanKillsGenerator<'_, 'tcx> {
|
|||
|
||||
if places_conflict {
|
||||
let location_index = self.location_table.mid_index(location);
|
||||
self.all_facts.loan_killed_at.push((borrow_index, location_index));
|
||||
self.facts.loan_killed_at.push((borrow_index, location_index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -140,9 +140,9 @@ impl<'tcx> LoanKillsGenerator<'_, 'tcx> {
|
|||
fn record_killed_borrows_for_local(&mut self, local: Local, location: Location) {
|
||||
if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) {
|
||||
let location_index = self.location_table.mid_index(location);
|
||||
self.all_facts.loan_killed_at.reserve(borrow_indices.len());
|
||||
self.facts.loan_killed_at.reserve(borrow_indices.len());
|
||||
for &borrow_index in borrow_indices {
|
||||
self.all_facts.loan_killed_at.push((borrow_index, location_index));
|
||||
self.facts.loan_killed_at.push((borrow_index, location_index));
|
||||
}
|
||||
}
|
||||
}
|
||||
223
compiler/rustc_borrowck/src/polonius/legacy/mod.rs
Normal file
223
compiler/rustc_borrowck/src/polonius/legacy/mod.rs
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
//! Functions dedicated to fact generation for the `-Zpolonius=legacy` datalog implementation.
|
||||
//!
|
||||
//! Will be removed in the future, once the in-tree `-Zpolonius=next` implementation reaches feature
|
||||
//! parity.
|
||||
|
||||
use std::iter;
|
||||
|
||||
use either::Either;
|
||||
use rustc_middle::mir::{Body, Local, LocalKind, Location, START_BLOCK};
|
||||
use rustc_middle::ty::{GenericArg, TyCtxt};
|
||||
use rustc_mir_dataflow::move_paths::{InitKind, InitLocation, MoveData};
|
||||
use tracing::debug;
|
||||
|
||||
use crate::borrow_set::BorrowSet;
|
||||
use crate::constraints::OutlivesConstraint;
|
||||
use crate::facts::{AllFacts, PoloniusRegionVid};
|
||||
use crate::location::LocationTable;
|
||||
use crate::type_check::MirTypeckRegionConstraints;
|
||||
use crate::type_check::free_region_relations::UniversalRegionRelations;
|
||||
use crate::universal_regions::UniversalRegions;
|
||||
|
||||
mod accesses;
|
||||
mod loan_invalidations;
|
||||
mod loan_kills;
|
||||
|
||||
/// When requested, emit most of the facts needed by polonius:
|
||||
/// - moves and assignments
|
||||
/// - universal regions and their relations
|
||||
/// - CFG points and edges
|
||||
/// - loan kills
|
||||
/// - loan invalidations
|
||||
/// - access facts such as variable definitions, uses, drops, and path accesses
|
||||
/// - outlives constraints
|
||||
///
|
||||
/// The rest of the facts are emitted during typeck and liveness.
|
||||
pub(crate) fn emit_facts<'tcx>(
|
||||
all_facts: &mut Option<AllFacts>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
location_table: &LocationTable,
|
||||
body: &Body<'tcx>,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
universal_region_relations: &UniversalRegionRelations<'tcx>,
|
||||
constraints: &MirTypeckRegionConstraints<'tcx>,
|
||||
) {
|
||||
let Some(facts) = all_facts else {
|
||||
// We don't do anything if there are no facts to fill.
|
||||
return;
|
||||
};
|
||||
let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation");
|
||||
emit_move_facts(facts, body, location_table, move_data);
|
||||
emit_universal_region_facts(facts, borrow_set, universal_region_relations);
|
||||
loan_kills::emit_loan_kills(tcx, facts, body, location_table, borrow_set);
|
||||
loan_invalidations::emit_loan_invalidations(tcx, facts, body, location_table, borrow_set);
|
||||
accesses::emit_access_facts(
|
||||
tcx,
|
||||
facts,
|
||||
body,
|
||||
location_table,
|
||||
move_data,
|
||||
&universal_region_relations.universal_regions,
|
||||
);
|
||||
emit_outlives_facts(facts, location_table, constraints);
|
||||
}
|
||||
|
||||
/// Emit facts needed for move/init analysis: moves and assignments.
|
||||
fn emit_move_facts(
|
||||
facts: &mut AllFacts,
|
||||
body: &Body<'_>,
|
||||
location_table: &LocationTable,
|
||||
move_data: &MoveData<'_>,
|
||||
) {
|
||||
facts.path_is_var.extend(move_data.rev_lookup.iter_locals_enumerated().map(|(l, r)| (r, l)));
|
||||
|
||||
for (child, move_path) in move_data.move_paths.iter_enumerated() {
|
||||
if let Some(parent) = move_path.parent {
|
||||
facts.child_path.push((child, parent));
|
||||
}
|
||||
}
|
||||
|
||||
let fn_entry_start =
|
||||
location_table.start_index(Location { block: START_BLOCK, statement_index: 0 });
|
||||
|
||||
// initialized_at
|
||||
for init in move_data.inits.iter() {
|
||||
match init.location {
|
||||
InitLocation::Statement(location) => {
|
||||
let block_data = &body[location.block];
|
||||
let is_terminator = location.statement_index == block_data.statements.len();
|
||||
|
||||
if is_terminator && init.kind == InitKind::NonPanicPathOnly {
|
||||
// We are at the terminator of an init that has a panic path,
|
||||
// and where the init should not happen on panic
|
||||
|
||||
for successor in block_data.terminator().successors() {
|
||||
if body[successor].is_cleanup {
|
||||
continue;
|
||||
}
|
||||
|
||||
// The initialization happened in (or rather, when arriving at)
|
||||
// the successors, but not in the unwind block.
|
||||
let first_statement = Location { block: successor, statement_index: 0 };
|
||||
facts
|
||||
.path_assigned_at_base
|
||||
.push((init.path, location_table.start_index(first_statement)));
|
||||
}
|
||||
} else {
|
||||
// In all other cases, the initialization just happens at the
|
||||
// midpoint, like any other effect.
|
||||
facts
|
||||
.path_assigned_at_base
|
||||
.push((init.path, location_table.mid_index(location)));
|
||||
}
|
||||
}
|
||||
// Arguments are initialized on function entry
|
||||
InitLocation::Argument(local) => {
|
||||
assert!(body.local_kind(local) == LocalKind::Arg);
|
||||
facts.path_assigned_at_base.push((init.path, fn_entry_start));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (local, path) in move_data.rev_lookup.iter_locals_enumerated() {
|
||||
if body.local_kind(local) != LocalKind::Arg {
|
||||
// Non-arguments start out deinitialised; we simulate this with an
|
||||
// initial move:
|
||||
facts.path_moved_at_base.push((path, fn_entry_start));
|
||||
}
|
||||
}
|
||||
|
||||
// moved_out_at
|
||||
// deinitialisation is assumed to always happen!
|
||||
facts
|
||||
.path_moved_at_base
|
||||
.extend(move_data.moves.iter().map(|mo| (mo.path, location_table.mid_index(mo.source))));
|
||||
}
|
||||
|
||||
/// Emit universal regions facts, and their relations.
|
||||
fn emit_universal_region_facts(
|
||||
facts: &mut AllFacts,
|
||||
borrow_set: &BorrowSet<'_>,
|
||||
universal_region_relations: &UniversalRegionRelations<'_>,
|
||||
) {
|
||||
// 1: universal regions are modeled in Polonius as a pair:
|
||||
// - the universal region vid itself.
|
||||
// - a "placeholder loan" associated to this universal region. Since they don't exist in
|
||||
// the `borrow_set`, their `BorrowIndex` are synthesized as the universal region index
|
||||
// added to the existing number of loans, as if they succeeded them in the set.
|
||||
//
|
||||
let universal_regions = &universal_region_relations.universal_regions;
|
||||
facts
|
||||
.universal_region
|
||||
.extend(universal_regions.universal_regions_iter().map(PoloniusRegionVid::from));
|
||||
let borrow_count = borrow_set.len();
|
||||
debug!(
|
||||
"emit_universal_region_facts: polonius placeholders, num_universals={}, borrow_count={}",
|
||||
universal_regions.len(),
|
||||
borrow_count
|
||||
);
|
||||
|
||||
for universal_region in universal_regions.universal_regions_iter() {
|
||||
let universal_region_idx = universal_region.index();
|
||||
let placeholder_loan_idx = borrow_count + universal_region_idx;
|
||||
facts.placeholder.push((universal_region.into(), placeholder_loan_idx.into()));
|
||||
}
|
||||
|
||||
// 2: the universal region relations `outlives` constraints are emitted as
|
||||
// `known_placeholder_subset` facts.
|
||||
for (fr1, fr2) in universal_region_relations.known_outlives() {
|
||||
if fr1 != fr2 {
|
||||
debug!(
|
||||
"emit_universal_region_facts: emitting polonius `known_placeholder_subset` \
|
||||
fr1={:?}, fr2={:?}",
|
||||
fr1, fr2
|
||||
);
|
||||
facts.known_placeholder_subset.push((fr1.into(), fr2.into()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// For every potentially drop()-touched region `region` in `local`'s type
|
||||
/// (`kind`), emit a `drop_of_var_derefs_origin(local, origin)` fact.
|
||||
pub(crate) fn emit_drop_facts<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
local: Local,
|
||||
kind: &GenericArg<'tcx>,
|
||||
universal_regions: &UniversalRegions<'tcx>,
|
||||
all_facts: &mut Option<AllFacts>,
|
||||
) {
|
||||
debug!("emit_drop_facts(local={:?}, kind={:?}", local, kind);
|
||||
let Some(facts) = all_facts.as_mut() else { return };
|
||||
let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation");
|
||||
tcx.for_each_free_region(kind, |drop_live_region| {
|
||||
let region_vid = universal_regions.to_region_vid(drop_live_region);
|
||||
facts.drop_of_var_derefs_origin.push((local, region_vid.into()));
|
||||
});
|
||||
}
|
||||
|
||||
/// Emit facts about the outlives constraints: the `subset` base relation, i.e. not a transitive
|
||||
/// closure.
|
||||
fn emit_outlives_facts<'tcx>(
|
||||
facts: &mut AllFacts,
|
||||
location_table: &LocationTable,
|
||||
constraints: &MirTypeckRegionConstraints<'tcx>,
|
||||
) {
|
||||
facts.subset_base.extend(constraints.outlives_constraints.outlives().iter().flat_map(
|
||||
|constraint: &OutlivesConstraint<'_>| {
|
||||
if let Some(from_location) = constraint.locations.from_location() {
|
||||
Either::Left(iter::once((
|
||||
constraint.sup.into(),
|
||||
constraint.sub.into(),
|
||||
location_table.mid_index(from_location),
|
||||
)))
|
||||
} else {
|
||||
Either::Right(
|
||||
location_table.all_points().map(move |location| {
|
||||
(constraint.sup.into(), constraint.sub.into(), location)
|
||||
}),
|
||||
)
|
||||
}
|
||||
},
|
||||
));
|
||||
}
|
||||
|
|
@ -1,184 +1 @@
|
|||
//! Functions dedicated to fact generation for the `-Zpolonius=legacy` datalog implementation.
|
||||
//!
|
||||
//! Will be removed in the future, once the in-tree `-Zpolonius=next` implementation reaches feature
|
||||
//! parity.
|
||||
|
||||
use rustc_middle::mir::{Body, LocalKind, Location, START_BLOCK};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_mir_dataflow::move_paths::{InitKind, InitLocation, MoveData};
|
||||
use tracing::debug;
|
||||
|
||||
use crate::borrow_set::BorrowSet;
|
||||
use crate::facts::{AllFacts, PoloniusRegionVid};
|
||||
use crate::location::LocationTable;
|
||||
use crate::type_check::free_region_relations::UniversalRegionRelations;
|
||||
|
||||
mod loan_invalidations;
|
||||
mod loan_kills;
|
||||
|
||||
/// When requested, emit most of the facts needed by polonius:
|
||||
/// - moves and assignments
|
||||
/// - universal regions and their relations
|
||||
/// - CFG points and edges
|
||||
/// - loan kills
|
||||
/// - loan invalidations
|
||||
///
|
||||
/// The rest of the facts are emitted during typeck and liveness.
|
||||
pub(crate) fn emit_facts<'tcx>(
|
||||
all_facts: &mut Option<AllFacts>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
location_table: &LocationTable,
|
||||
body: &Body<'tcx>,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
move_data: &MoveData<'_>,
|
||||
universal_region_relations: &UniversalRegionRelations<'_>,
|
||||
) {
|
||||
let Some(all_facts) = all_facts else {
|
||||
// We don't do anything if there are no facts to fill.
|
||||
return;
|
||||
};
|
||||
let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation");
|
||||
emit_move_facts(all_facts, move_data, location_table, body);
|
||||
emit_universal_region_facts(all_facts, borrow_set, universal_region_relations);
|
||||
emit_cfg_and_loan_kills_facts(all_facts, tcx, location_table, body, borrow_set);
|
||||
emit_loan_invalidations_facts(all_facts, tcx, location_table, body, borrow_set);
|
||||
}
|
||||
|
||||
/// Emit facts needed for move/init analysis: moves and assignments.
|
||||
fn emit_move_facts(
|
||||
all_facts: &mut AllFacts,
|
||||
move_data: &MoveData<'_>,
|
||||
location_table: &LocationTable,
|
||||
body: &Body<'_>,
|
||||
) {
|
||||
all_facts
|
||||
.path_is_var
|
||||
.extend(move_data.rev_lookup.iter_locals_enumerated().map(|(l, r)| (r, l)));
|
||||
|
||||
for (child, move_path) in move_data.move_paths.iter_enumerated() {
|
||||
if let Some(parent) = move_path.parent {
|
||||
all_facts.child_path.push((child, parent));
|
||||
}
|
||||
}
|
||||
|
||||
let fn_entry_start =
|
||||
location_table.start_index(Location { block: START_BLOCK, statement_index: 0 });
|
||||
|
||||
// initialized_at
|
||||
for init in move_data.inits.iter() {
|
||||
match init.location {
|
||||
InitLocation::Statement(location) => {
|
||||
let block_data = &body[location.block];
|
||||
let is_terminator = location.statement_index == block_data.statements.len();
|
||||
|
||||
if is_terminator && init.kind == InitKind::NonPanicPathOnly {
|
||||
// We are at the terminator of an init that has a panic path,
|
||||
// and where the init should not happen on panic
|
||||
|
||||
for successor in block_data.terminator().successors() {
|
||||
if body[successor].is_cleanup {
|
||||
continue;
|
||||
}
|
||||
|
||||
// The initialization happened in (or rather, when arriving at)
|
||||
// the successors, but not in the unwind block.
|
||||
let first_statement = Location { block: successor, statement_index: 0 };
|
||||
all_facts
|
||||
.path_assigned_at_base
|
||||
.push((init.path, location_table.start_index(first_statement)));
|
||||
}
|
||||
} else {
|
||||
// In all other cases, the initialization just happens at the
|
||||
// midpoint, like any other effect.
|
||||
all_facts
|
||||
.path_assigned_at_base
|
||||
.push((init.path, location_table.mid_index(location)));
|
||||
}
|
||||
}
|
||||
// Arguments are initialized on function entry
|
||||
InitLocation::Argument(local) => {
|
||||
assert!(body.local_kind(local) == LocalKind::Arg);
|
||||
all_facts.path_assigned_at_base.push((init.path, fn_entry_start));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (local, path) in move_data.rev_lookup.iter_locals_enumerated() {
|
||||
if body.local_kind(local) != LocalKind::Arg {
|
||||
// Non-arguments start out deinitialised; we simulate this with an
|
||||
// initial move:
|
||||
all_facts.path_moved_at_base.push((path, fn_entry_start));
|
||||
}
|
||||
}
|
||||
|
||||
// moved_out_at
|
||||
// deinitialisation is assumed to always happen!
|
||||
all_facts
|
||||
.path_moved_at_base
|
||||
.extend(move_data.moves.iter().map(|mo| (mo.path, location_table.mid_index(mo.source))));
|
||||
}
|
||||
|
||||
/// Emit universal regions facts, and their relations.
|
||||
fn emit_universal_region_facts(
|
||||
all_facts: &mut AllFacts,
|
||||
borrow_set: &BorrowSet<'_>,
|
||||
universal_region_relations: &UniversalRegionRelations<'_>,
|
||||
) {
|
||||
// 1: universal regions are modeled in Polonius as a pair:
|
||||
// - the universal region vid itself.
|
||||
// - a "placeholder loan" associated to this universal region. Since they don't exist in
|
||||
// the `borrow_set`, their `BorrowIndex` are synthesized as the universal region index
|
||||
// added to the existing number of loans, as if they succeeded them in the set.
|
||||
//
|
||||
let universal_regions = &universal_region_relations.universal_regions;
|
||||
all_facts
|
||||
.universal_region
|
||||
.extend(universal_regions.universal_regions_iter().map(PoloniusRegionVid::from));
|
||||
let borrow_count = borrow_set.len();
|
||||
debug!(
|
||||
"emit_universal_region_facts: polonius placeholders, num_universals={}, borrow_count={}",
|
||||
universal_regions.len(),
|
||||
borrow_count
|
||||
);
|
||||
|
||||
for universal_region in universal_regions.universal_regions_iter() {
|
||||
let universal_region_idx = universal_region.index();
|
||||
let placeholder_loan_idx = borrow_count + universal_region_idx;
|
||||
all_facts.placeholder.push((universal_region.into(), placeholder_loan_idx.into()));
|
||||
}
|
||||
|
||||
// 2: the universal region relations `outlives` constraints are emitted as
|
||||
// `known_placeholder_subset` facts.
|
||||
for (fr1, fr2) in universal_region_relations.known_outlives() {
|
||||
if fr1 != fr2 {
|
||||
debug!(
|
||||
"emit_universal_region_facts: emitting polonius `known_placeholder_subset` \
|
||||
fr1={:?}, fr2={:?}",
|
||||
fr1, fr2
|
||||
);
|
||||
all_facts.known_placeholder_subset.push((fr1.into(), fr2.into()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Emit facts about loan invalidations.
|
||||
fn emit_loan_invalidations_facts<'tcx>(
|
||||
all_facts: &mut AllFacts,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
location_table: &LocationTable,
|
||||
body: &Body<'tcx>,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
) {
|
||||
loan_invalidations::emit_loan_invalidations(tcx, all_facts, location_table, body, borrow_set);
|
||||
}
|
||||
|
||||
/// Emit facts about CFG points and edges, as well as locations where loans are killed.
|
||||
fn emit_cfg_and_loan_kills_facts<'tcx>(
|
||||
all_facts: &mut AllFacts,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
location_table: &LocationTable,
|
||||
body: &Body<'tcx>,
|
||||
borrow_set: &BorrowSet<'tcx>,
|
||||
) {
|
||||
loan_kills::emit_loan_kills(tcx, all_facts, location_table, body, borrow_set);
|
||||
}
|
||||
pub(crate) mod legacy;
|
||||
|
|
|
|||
|
|
@ -134,12 +134,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
// the hidden type becomes the opaque type itself. In this case, this was an opaque
|
||||
// usage of the opaque type and we can ignore it. This check is mirrored in typeck's
|
||||
// writeback.
|
||||
// FIXME(-Znext-solver): This should be unnecessary with the new solver.
|
||||
if let ty::Alias(ty::Opaque, alias_ty) = ty.kind()
|
||||
&& alias_ty.def_id == opaque_type_key.def_id.to_def_id()
|
||||
&& alias_ty.args == opaque_type_key.args
|
||||
{
|
||||
continue;
|
||||
if !infcx.next_trait_solver() {
|
||||
if let ty::Alias(ty::Opaque, alias_ty) = ty.kind()
|
||||
&& alias_ty.def_id == opaque_type_key.def_id.to_def_id()
|
||||
&& alias_ty.args == opaque_type_key.args
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Sometimes two opaque types are the same only after we remap the generic parameters
|
||||
// back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ use crate::region_infer::values::LivenessValues;
|
|||
use crate::universal_regions::UniversalRegions;
|
||||
|
||||
mod local_use_map;
|
||||
mod polonius;
|
||||
mod trace;
|
||||
|
||||
/// Combines liveness analysis with initialization analysis to
|
||||
|
|
@ -45,8 +44,6 @@ pub(super) fn generate<'a, 'tcx>(
|
|||
let (relevant_live_locals, boring_locals) =
|
||||
compute_relevant_live_locals(typeck.tcx(), &free_regions, body);
|
||||
|
||||
polonius::populate_access_facts(typeck, body, move_data);
|
||||
|
||||
trace::trace(
|
||||
typeck,
|
||||
body,
|
||||
|
|
|
|||
|
|
@ -1,136 +0,0 @@
|
|||
use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
|
||||
use rustc_middle::mir::{Body, Local, Location, Place};
|
||||
use rustc_middle::ty::GenericArg;
|
||||
use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
|
||||
use tracing::debug;
|
||||
|
||||
use super::TypeChecker;
|
||||
use crate::def_use::{self, DefUse};
|
||||
use crate::location::{LocationIndex, LocationTable};
|
||||
|
||||
type VarPointRelation = Vec<(Local, LocationIndex)>;
|
||||
type PathPointRelation = Vec<(MovePathIndex, LocationIndex)>;
|
||||
|
||||
struct UseFactsExtractor<'a, 'tcx> {
|
||||
var_defined_at: &'a mut VarPointRelation,
|
||||
var_used_at: &'a mut VarPointRelation,
|
||||
location_table: &'a LocationTable,
|
||||
var_dropped_at: &'a mut VarPointRelation,
|
||||
move_data: &'a MoveData<'tcx>,
|
||||
path_accessed_at_base: &'a mut PathPointRelation,
|
||||
}
|
||||
|
||||
// A Visitor to walk through the MIR and extract point-wise facts
|
||||
impl<'tcx> UseFactsExtractor<'_, 'tcx> {
|
||||
fn location_to_index(&self, location: Location) -> LocationIndex {
|
||||
self.location_table.mid_index(location)
|
||||
}
|
||||
|
||||
fn insert_def(&mut self, local: Local, location: Location) {
|
||||
debug!("UseFactsExtractor::insert_def()");
|
||||
self.var_defined_at.push((local, self.location_to_index(location)));
|
||||
}
|
||||
|
||||
fn insert_use(&mut self, local: Local, location: Location) {
|
||||
debug!("UseFactsExtractor::insert_use()");
|
||||
self.var_used_at.push((local, self.location_to_index(location)));
|
||||
}
|
||||
|
||||
fn insert_drop_use(&mut self, local: Local, location: Location) {
|
||||
debug!("UseFactsExtractor::insert_drop_use()");
|
||||
self.var_dropped_at.push((local, self.location_to_index(location)));
|
||||
}
|
||||
|
||||
fn insert_path_access(&mut self, path: MovePathIndex, location: Location) {
|
||||
debug!("UseFactsExtractor::insert_path_access({:?}, {:?})", path, location);
|
||||
self.path_accessed_at_base.push((path, self.location_to_index(location)));
|
||||
}
|
||||
|
||||
fn place_to_mpi(&self, place: &Place<'tcx>) -> Option<MovePathIndex> {
|
||||
match self.move_data.rev_lookup.find(place.as_ref()) {
|
||||
LookupResult::Exact(mpi) => Some(mpi),
|
||||
LookupResult::Parent(mmpi) => mmpi,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Visitor<'tcx> for UseFactsExtractor<'a, 'tcx> {
|
||||
fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) {
|
||||
match def_use::categorize(context) {
|
||||
Some(DefUse::Def) => self.insert_def(local, location),
|
||||
Some(DefUse::Use) => self.insert_use(local, location),
|
||||
Some(DefUse::Drop) => self.insert_drop_use(local, location),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
|
||||
self.super_place(place, context, location);
|
||||
match context {
|
||||
PlaceContext::NonMutatingUse(_) => {
|
||||
if let Some(mpi) = self.place_to_mpi(place) {
|
||||
self.insert_path_access(mpi, location);
|
||||
}
|
||||
}
|
||||
|
||||
PlaceContext::MutatingUse(MutatingUseContext::Borrow) => {
|
||||
if let Some(mpi) = self.place_to_mpi(place) {
|
||||
self.insert_path_access(mpi, location);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn populate_access_facts<'a, 'tcx>(
|
||||
typeck: &mut TypeChecker<'a, 'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
) {
|
||||
if let Some(facts) = typeck.all_facts.as_mut() {
|
||||
debug!("populate_access_facts()");
|
||||
let location_table = typeck.location_table;
|
||||
|
||||
let mut extractor = UseFactsExtractor {
|
||||
var_defined_at: &mut facts.var_defined_at,
|
||||
var_used_at: &mut facts.var_used_at,
|
||||
var_dropped_at: &mut facts.var_dropped_at,
|
||||
path_accessed_at_base: &mut facts.path_accessed_at_base,
|
||||
location_table,
|
||||
move_data,
|
||||
};
|
||||
extractor.visit_body(body);
|
||||
|
||||
for (local, local_decl) in body.local_decls.iter_enumerated() {
|
||||
debug!(
|
||||
"add use_of_var_derefs_origin facts - local={:?}, type={:?}",
|
||||
local, local_decl.ty
|
||||
);
|
||||
let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
|
||||
let universal_regions = &typeck.universal_regions;
|
||||
typeck.infcx.tcx.for_each_free_region(&local_decl.ty, |region| {
|
||||
let region_vid = universal_regions.to_region_vid(region);
|
||||
facts.use_of_var_derefs_origin.push((local, region_vid.into()));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// For every potentially drop()-touched region `region` in `local`'s type
|
||||
/// (`kind`), emit a Polonius `use_of_var_derefs_origin(local, origin)` fact.
|
||||
pub(super) fn add_drop_of_var_derefs_origin<'tcx>(
|
||||
typeck: &mut TypeChecker<'_, 'tcx>,
|
||||
local: Local,
|
||||
kind: &GenericArg<'tcx>,
|
||||
) {
|
||||
debug!("add_drop_of_var_derefs_origin(local={:?}, kind={:?}", local, kind);
|
||||
if let Some(facts) = typeck.all_facts.as_mut() {
|
||||
let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
|
||||
let universal_regions = &typeck.universal_regions;
|
||||
typeck.infcx.tcx.for_each_free_region(kind, |drop_live_region| {
|
||||
let region_vid = universal_regions.to_region_vid(drop_live_region);
|
||||
facts.drop_of_var_derefs_origin.push((local, region_vid.into()));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -15,9 +15,9 @@ use rustc_trait_selection::traits::query::type_op::{DropckOutlives, TypeOp, Type
|
|||
use tracing::debug;
|
||||
|
||||
use crate::location::RichLocation;
|
||||
use crate::polonius;
|
||||
use crate::region_infer::values::{self, LiveLoans};
|
||||
use crate::type_check::liveness::local_use_map::LocalUseMap;
|
||||
use crate::type_check::liveness::polonius;
|
||||
use crate::type_check::{NormalizeLocation, TypeChecker};
|
||||
|
||||
/// This is the heart of the liveness computation. For each variable X
|
||||
|
|
@ -590,7 +590,13 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
|
|||
// the destructor and must be live at this point.
|
||||
for &kind in &drop_data.dropck_result.kinds {
|
||||
Self::make_all_regions_live(self.elements, self.typeck, kind, live_at);
|
||||
polonius::add_drop_of_var_derefs_origin(self.typeck, dropped_local, &kind);
|
||||
polonius::legacy::emit_drop_facts(
|
||||
self.typeck.tcx(),
|
||||
dropped_local,
|
||||
&kind,
|
||||
self.typeck.universal_regions,
|
||||
self.typeck.all_facts,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
use std::rc::Rc;
|
||||
use std::{fmt, iter, mem};
|
||||
|
||||
use either::Either;
|
||||
use rustc_abi::{FIRST_VARIANT, FieldIdx};
|
||||
use rustc_data_structures::frozen::Frozen;
|
||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||
|
|
@ -40,8 +39,7 @@ use rustc_mir_dataflow::move_paths::MoveData;
|
|||
use rustc_mir_dataflow::points::DenseLocationMap;
|
||||
use rustc_span::def_id::CRATE_DEF_ID;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{DUMMY_SP, Span};
|
||||
use rustc_span::{DUMMY_SP, Span, sym};
|
||||
use rustc_trait_selection::traits::query::type_op::custom::{
|
||||
CustomTypeOp, scrape_region_constraints,
|
||||
};
|
||||
|
|
@ -107,7 +105,6 @@ mod relate_tys;
|
|||
/// # Parameters
|
||||
///
|
||||
/// - `infcx` -- inference context to use
|
||||
/// - `param_env` -- parameter environment to use for trait solving
|
||||
/// - `body` -- MIR body to type-check
|
||||
/// - `promoted` -- map of promoted constants within `body`
|
||||
/// - `universal_regions` -- the universal regions from `body`s function signature
|
||||
|
|
@ -155,7 +152,7 @@ pub(crate) fn type_check<'a, 'tcx>(
|
|||
|
||||
debug!(?normalized_inputs_and_output);
|
||||
|
||||
let mut checker = TypeChecker {
|
||||
let mut typeck = TypeChecker {
|
||||
infcx,
|
||||
last_span: body.span,
|
||||
body,
|
||||
|
|
@ -171,24 +168,22 @@ pub(crate) fn type_check<'a, 'tcx>(
|
|||
constraints: &mut constraints,
|
||||
};
|
||||
|
||||
checker.check_user_type_annotations();
|
||||
typeck.check_user_type_annotations();
|
||||
|
||||
let mut verifier = TypeVerifier { cx: &mut checker, promoted, last_span: body.span };
|
||||
let mut verifier = TypeVerifier { typeck: &mut typeck, promoted, last_span: body.span };
|
||||
verifier.visit_body(body);
|
||||
|
||||
checker.typeck_mir(body);
|
||||
checker.equate_inputs_and_outputs(body, &normalized_inputs_and_output);
|
||||
checker.check_signature_annotation(body);
|
||||
typeck.typeck_mir(body);
|
||||
typeck.equate_inputs_and_outputs(body, &normalized_inputs_and_output);
|
||||
typeck.check_signature_annotation(body);
|
||||
|
||||
liveness::generate(&mut checker, body, &elements, flow_inits, move_data);
|
||||
liveness::generate(&mut typeck, body, &elements, flow_inits, move_data);
|
||||
|
||||
translate_outlives_facts(&mut checker);
|
||||
let opaque_type_values = infcx.take_opaque_types();
|
||||
|
||||
let opaque_type_values = opaque_type_values
|
||||
let opaque_type_values = infcx
|
||||
.take_opaque_types()
|
||||
.into_iter()
|
||||
.map(|(opaque_type_key, decl)| {
|
||||
let _: Result<_, ErrorGuaranteed> = checker.fully_perform_op(
|
||||
let _: Result<_, ErrorGuaranteed> = typeck.fully_perform_op(
|
||||
Locations::All(body.span),
|
||||
ConstraintCategory::OpaqueType,
|
||||
CustomTypeOp::new(
|
||||
|
|
@ -218,11 +213,11 @@ pub(crate) fn type_check<'a, 'tcx>(
|
|||
match region.kind() {
|
||||
ty::ReVar(_) => region,
|
||||
ty::RePlaceholder(placeholder) => {
|
||||
checker.constraints.placeholder_region(infcx, placeholder)
|
||||
typeck.constraints.placeholder_region(infcx, placeholder)
|
||||
}
|
||||
_ => ty::Region::new_var(
|
||||
infcx.tcx,
|
||||
checker.universal_regions.to_region_vid(region),
|
||||
typeck.universal_regions.to_region_vid(region),
|
||||
),
|
||||
}
|
||||
});
|
||||
|
|
@ -234,30 +229,6 @@ pub(crate) fn type_check<'a, 'tcx>(
|
|||
MirTypeckResults { constraints, universal_region_relations, opaque_type_values }
|
||||
}
|
||||
|
||||
fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) {
|
||||
if let Some(facts) = typeck.all_facts {
|
||||
let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
|
||||
let location_table = typeck.location_table;
|
||||
facts.subset_base.extend(
|
||||
typeck.constraints.outlives_constraints.outlives().iter().flat_map(
|
||||
|constraint: &OutlivesConstraint<'_>| {
|
||||
if let Some(from_location) = constraint.locations.from_location() {
|
||||
Either::Left(iter::once((
|
||||
constraint.sup.into(),
|
||||
constraint.sub.into(),
|
||||
location_table.mid_index(from_location),
|
||||
)))
|
||||
} else {
|
||||
Either::Right(location_table.all_points().map(move |location| {
|
||||
(constraint.sup.into(), constraint.sub.into(), location)
|
||||
}))
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn mirbug(tcx: TyCtxt<'_>, span: Span, msg: String) {
|
||||
// We sometimes see MIR failures (notably predicate failures) due to
|
||||
|
|
@ -276,7 +247,7 @@ enum FieldAccessError {
|
|||
/// type, calling `span_mirbug` and returning an error type if there
|
||||
/// is a problem.
|
||||
struct TypeVerifier<'a, 'b, 'tcx> {
|
||||
cx: &'a mut TypeChecker<'b, 'tcx>,
|
||||
typeck: &'a mut TypeChecker<'b, 'tcx>,
|
||||
promoted: &'b IndexSlice<Promoted, Body<'tcx>>,
|
||||
last_span: Span,
|
||||
}
|
||||
|
|
@ -298,9 +269,9 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
|||
self.super_const_operand(constant, location);
|
||||
let ty = self.sanitize_type(constant, constant.const_.ty());
|
||||
|
||||
self.cx.infcx.tcx.for_each_free_region(&ty, |live_region| {
|
||||
let live_region_vid = self.cx.universal_regions.to_region_vid(live_region);
|
||||
self.cx.constraints.liveness_constraints.add_location(live_region_vid, location);
|
||||
self.typeck.infcx.tcx.for_each_free_region(&ty, |live_region| {
|
||||
let live_region_vid = self.typeck.universal_regions.to_region_vid(live_region);
|
||||
self.typeck.constraints.liveness_constraints.add_location(live_region_vid, location);
|
||||
});
|
||||
|
||||
// HACK(compiler-errors): Constants that are gathered into Body.required_consts
|
||||
|
|
@ -312,14 +283,14 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
|||
};
|
||||
|
||||
if let Some(annotation_index) = constant.user_ty {
|
||||
if let Err(terr) = self.cx.relate_type_and_user_type(
|
||||
if let Err(terr) = self.typeck.relate_type_and_user_type(
|
||||
constant.const_.ty(),
|
||||
ty::Invariant,
|
||||
&UserTypeProjection { base: annotation_index, projs: vec![] },
|
||||
locations,
|
||||
ConstraintCategory::Boring,
|
||||
) {
|
||||
let annotation = &self.cx.user_type_annotations[annotation_index];
|
||||
let annotation = &self.typeck.user_type_annotations[annotation_index];
|
||||
span_mirbug!(
|
||||
self,
|
||||
constant,
|
||||
|
|
@ -348,9 +319,12 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
|||
promoted: &Body<'tcx>,
|
||||
ty,
|
||||
san_ty| {
|
||||
if let Err(terr) =
|
||||
verifier.cx.eq_types(ty, san_ty, locations, ConstraintCategory::Boring)
|
||||
{
|
||||
if let Err(terr) = verifier.typeck.eq_types(
|
||||
ty,
|
||||
san_ty,
|
||||
locations,
|
||||
ConstraintCategory::Boring,
|
||||
) {
|
||||
span_mirbug!(
|
||||
verifier,
|
||||
promoted,
|
||||
|
|
@ -368,21 +342,21 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
|||
let promoted_ty = promoted_body.return_ty();
|
||||
check_err(self, promoted_body, ty, promoted_ty);
|
||||
} else {
|
||||
self.cx.ascribe_user_type(
|
||||
self.typeck.ascribe_user_type(
|
||||
constant.const_.ty(),
|
||||
ty::UserType::new(ty::UserTypeKind::TypeOf(uv.def, UserArgs {
|
||||
args: uv.args,
|
||||
user_self_ty: None,
|
||||
})),
|
||||
locations.span(self.cx.body),
|
||||
locations.span(self.typeck.body),
|
||||
);
|
||||
}
|
||||
} else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
|
||||
let unnormalized_ty = tcx.type_of(static_def_id).instantiate_identity();
|
||||
let normalized_ty = self.cx.normalize(unnormalized_ty, locations);
|
||||
let normalized_ty = self.typeck.normalize(unnormalized_ty, locations);
|
||||
let literal_ty = constant.const_.ty().builtin_deref(true).unwrap();
|
||||
|
||||
if let Err(terr) = self.cx.eq_types(
|
||||
if let Err(terr) = self.typeck.eq_types(
|
||||
literal_ty,
|
||||
normalized_ty,
|
||||
locations,
|
||||
|
|
@ -394,7 +368,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
|||
|
||||
if let ty::FnDef(def_id, args) = *constant.const_.ty().kind() {
|
||||
let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, args);
|
||||
self.cx.normalize_and_prove_instantiated_predicates(
|
||||
self.typeck.normalize_and_prove_instantiated_predicates(
|
||||
def_id,
|
||||
instantiated_predicates,
|
||||
locations,
|
||||
|
|
@ -404,7 +378,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
|||
tcx.impl_of_method(def_id).map(|imp| tcx.def_kind(imp)),
|
||||
Some(DefKind::Impl { of_trait: true })
|
||||
));
|
||||
self.cx.prove_predicates(
|
||||
self.typeck.prove_predicates(
|
||||
args.types().map(|ty| ty::ClauseKind::WellFormed(ty.into())),
|
||||
locations,
|
||||
ConstraintCategory::Boring,
|
||||
|
|
@ -438,7 +412,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
|||
local_decl.ty
|
||||
};
|
||||
|
||||
if let Err(terr) = self.cx.relate_type_and_user_type(
|
||||
if let Err(terr) = self.typeck.relate_type_and_user_type(
|
||||
ty,
|
||||
ty::Invariant,
|
||||
user_ty,
|
||||
|
|
@ -468,11 +442,11 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
|||
|
||||
impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
||||
fn body(&self) -> &Body<'tcx> {
|
||||
self.cx.body
|
||||
self.typeck.body
|
||||
}
|
||||
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.cx.infcx.tcx
|
||||
self.typeck.infcx.tcx
|
||||
}
|
||||
|
||||
fn sanitize_type(&mut self, parent: &dyn fmt::Debug, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
|
|
@ -522,7 +496,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
|||
// whether the bounds fully apply: in effect, the rule is
|
||||
// that if a value of some type could implement `Copy`, then
|
||||
// it must.
|
||||
self.cx.prove_trait_ref(
|
||||
self.typeck.prove_trait_ref(
|
||||
trait_ref,
|
||||
location.to_locations(),
|
||||
ConstraintCategory::CopyBound,
|
||||
|
|
@ -537,7 +511,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
|||
// checker on the promoted MIR, then transfer the constraints back to
|
||||
// the main MIR, changing the locations to the provided location.
|
||||
|
||||
let parent_body = mem::replace(&mut self.cx.body, promoted_body);
|
||||
let parent_body = mem::replace(&mut self.typeck.body, promoted_body);
|
||||
|
||||
// Use new sets of constraints and closure bounds so that we can
|
||||
// modify their locations.
|
||||
|
|
@ -548,18 +522,18 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
|||
// Don't try to add borrow_region facts for the promoted MIR
|
||||
|
||||
let mut swap_constraints = |this: &mut Self| {
|
||||
mem::swap(this.cx.all_facts, all_facts);
|
||||
mem::swap(&mut this.cx.constraints.outlives_constraints, &mut constraints);
|
||||
mem::swap(&mut this.cx.constraints.liveness_constraints, &mut liveness_constraints);
|
||||
mem::swap(this.typeck.all_facts, all_facts);
|
||||
mem::swap(&mut this.typeck.constraints.outlives_constraints, &mut constraints);
|
||||
mem::swap(&mut this.typeck.constraints.liveness_constraints, &mut liveness_constraints);
|
||||
};
|
||||
|
||||
swap_constraints(self);
|
||||
|
||||
self.visit_body(promoted_body);
|
||||
|
||||
self.cx.typeck_mir(promoted_body);
|
||||
self.typeck.typeck_mir(promoted_body);
|
||||
|
||||
self.cx.body = parent_body;
|
||||
self.typeck.body = parent_body;
|
||||
// Merge the outlives constraints back in, at the given location.
|
||||
swap_constraints(self);
|
||||
|
||||
|
|
@ -575,7 +549,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
|||
// temporary from the user's point of view.
|
||||
constraint.category = ConstraintCategory::Boring;
|
||||
}
|
||||
self.cx.constraints.outlives_constraints.push(constraint)
|
||||
self.typeck.constraints.outlives_constraints.push(constraint)
|
||||
}
|
||||
// If the region is live at least one location in the promoted MIR,
|
||||
// then add a liveness constraint to the main MIR for this region
|
||||
|
|
@ -585,7 +559,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
|||
// unordered.
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
for region in liveness_constraints.live_regions_unordered() {
|
||||
self.cx.constraints.liveness_constraints.add_location(region, location);
|
||||
self.typeck.constraints.liveness_constraints.add_location(region, location);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -669,13 +643,13 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
|||
},
|
||||
ProjectionElem::Field(field, fty) => {
|
||||
let fty = self.sanitize_type(place, fty);
|
||||
let fty = self.cx.normalize(fty, location);
|
||||
let fty = self.typeck.normalize(fty, location);
|
||||
match self.field_ty(place, base, field, location) {
|
||||
Ok(ty) => {
|
||||
let ty = self.cx.normalize(ty, location);
|
||||
let ty = self.typeck.normalize(ty, location);
|
||||
debug!(?fty, ?ty);
|
||||
|
||||
if let Err(terr) = self.cx.relate_types(
|
||||
if let Err(terr) = self.typeck.relate_types(
|
||||
ty,
|
||||
self.get_ambient_variance(context),
|
||||
fty,
|
||||
|
|
@ -707,8 +681,8 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
|||
}
|
||||
ProjectionElem::OpaqueCast(ty) => {
|
||||
let ty = self.sanitize_type(place, ty);
|
||||
let ty = self.cx.normalize(ty, location);
|
||||
self.cx
|
||||
let ty = self.typeck.normalize(ty, location);
|
||||
self.typeck
|
||||
.relate_types(
|
||||
ty,
|
||||
self.get_ambient_variance(context),
|
||||
|
|
@ -817,7 +791,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
|||
};
|
||||
|
||||
if let Some(field) = variant.fields.get(field) {
|
||||
Ok(self.cx.normalize(field.ty(tcx, args), location))
|
||||
Ok(self.typeck.normalize(field.ty(tcx, args), location))
|
||||
} else {
|
||||
Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() })
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@ use rustc_middle::traits::query::NoSolution;
|
|||
use rustc_middle::ty::fold::FnMutDelegate;
|
||||
use rustc_middle::ty::relate::combine::{super_combine_consts, super_combine_tys};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use crate::constraints::OutlivesConstraint;
|
||||
|
|
|
|||
|
|
@ -33,8 +33,7 @@ use rustc_middle::ty::{
|
|||
TyCtxt, TypeVisitableExt,
|
||||
};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::ErrorGuaranteed;
|
||||
use rustc_span::symbol::{kw, sym};
|
||||
use rustc_span::{ErrorGuaranteed, kw, sym};
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use crate::BorrowckInferCtxt;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ doctest = false
|
|||
# tidy-alphabetical-start
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||
rustc_attr = { path = "../rustc_attr" }
|
||||
rustc_attr_parsing = { path = "../rustc_attr_parsing" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
rustc_expand = { path = "../rustc_expand" }
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@ use rustc_ast::{
|
|||
self as ast, Fn, FnHeader, FnSig, Generics, ItemKind, Safety, Stmt, StmtKind, TyKind,
|
||||
};
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::{Ident, kw, sym};
|
||||
use rustc_span::{Ident, Span, kw, sym};
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
|
||||
use crate::errors;
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ use rustc_expand::base::*;
|
|||
use rustc_index::bit_set::GrowableBitSet;
|
||||
use rustc_parse::parser::Parser;
|
||||
use rustc_session::lint;
|
||||
use rustc_span::symbol::{Ident, Symbol, kw, sym};
|
||||
use rustc_span::{ErrorGuaranteed, InnerSpan, Span};
|
||||
use rustc_span::{ErrorGuaranteed, Ident, InnerSpan, Span, Symbol, kw, sym};
|
||||
use rustc_target::asm::InlineAsmArch;
|
||||
use smallvec::smallvec;
|
||||
use {rustc_ast as ast, rustc_parse_format as parse};
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@ use rustc_ast_pretty::pprust;
|
|||
use rustc_errors::PResult;
|
||||
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
|
||||
use rustc_parse::parser::Parser;
|
||||
use rustc_span::symbol::{Ident, Symbol, sym};
|
||||
use rustc_span::{DUMMY_SP, Span};
|
||||
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym};
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
use crate::edition_panic::use_panic_2021;
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@ use rustc_ast::{
|
|||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_expand::base::ExtCtxt;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::{Ident, Symbol, sym};
|
||||
use rustc_span::{Ident, Span, Symbol, sym};
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
|
||||
pub(super) struct Context<'cx, 'a> {
|
||||
|
|
|
|||
|
|
@ -20,8 +20,7 @@ mod llvm_enzyme {
|
|||
PatKind, TyKind,
|
||||
};
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::symbol::{Ident, kw, sym};
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_span::{Ident, Span, Symbol, kw, sym};
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
use tracing::{debug, trace};
|
||||
|
||||
|
|
@ -35,7 +34,7 @@ mod llvm_enzyme {
|
|||
FnRetTy::Default(_) => false,
|
||||
}
|
||||
}
|
||||
fn first_ident(x: &MetaItemInner) -> rustc_span::symbol::Ident {
|
||||
fn first_ident(x: &MetaItemInner) -> rustc_span::Ident {
|
||||
let segments = &x.meta_item().unwrap().path.segments;
|
||||
assert!(segments.len() == 1);
|
||||
segments[0].ident
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use rustc_ast::tokenstream::TokenStream;
|
|||
use rustc_errors::PResult;
|
||||
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
|
||||
use rustc_span::Span;
|
||||
use {rustc_ast as ast, rustc_attr as attr};
|
||||
use {rustc_ast as ast, rustc_attr_parsing as attr};
|
||||
|
||||
use crate::errors;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@ use rustc_ast as ast;
|
|||
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier};
|
||||
use rustc_feature::AttributeTemplate;
|
||||
use rustc_parse::validate_attr;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{Span, sym};
|
||||
|
||||
use crate::errors;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,8 +12,7 @@ use rustc_expand::configure;
|
|||
use rustc_feature::Features;
|
||||
use rustc_parse::parser::{ForceCollect, Parser};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{Span, sym};
|
||||
use smallvec::SmallVec;
|
||||
use tracing::instrument;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use rustc_ast::tokenstream::TokenStream;
|
|||
use rustc_ast::{ExprKind, LitKind, UnOp};
|
||||
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
|
||||
use rustc_session::errors::report_lit_error;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::Symbol;
|
||||
|
||||
use crate::errors;
|
||||
use crate::util::get_exprs_from_tts;
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@ use rustc_ast::token::{self, Token};
|
|||
use rustc_ast::tokenstream::{TokenStream, TokenTree};
|
||||
use rustc_ast::{AttrVec, DUMMY_NODE_ID, Expr, ExprKind, Path, Ty, TyKind};
|
||||
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacResult, MacroExpanderResult};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::{Ident, Symbol};
|
||||
use rustc_span::{Ident, Span, Symbol};
|
||||
|
||||
use crate::errors;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@ use rustc_expand::base::{
|
|||
use rustc_feature::AttributeTemplate;
|
||||
use rustc_parse::validate_attr;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::symbol::{Ident, sym};
|
||||
use rustc_span::{ErrorGuaranteed, Span};
|
||||
use rustc_span::{ErrorGuaranteed, Ident, Span, sym};
|
||||
|
||||
use crate::cfg_eval::cfg_eval;
|
||||
use crate::errors;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
use rustc_ast::{self as ast, Generics, ItemKind, MetaItem, VariantData};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::{Ident, kw, sym};
|
||||
use rustc_span::{Ident, Span, kw, sym};
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
|
||||
use crate::deriving::generic::ty::*;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
use rustc_ast::{self as ast, MetaItem};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{Span, sym};
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
|
||||
use crate::deriving::generic::ty::*;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use rustc_ast::MetaItem;
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::{Ident, sym};
|
||||
use rustc_span::{Ident, Span, sym};
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
use crate::deriving::generic::ty::*;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{BinOpKind, BorrowKind, Expr, ExprKind, MetaItem, Mutability};
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{Span, sym};
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
use crate::deriving::generic::ty::*;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use rustc_ast::{ExprKind, ItemKind, MetaItem, PatKind};
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::{Ident, sym};
|
||||
use rustc_span::{Ident, Span, sym};
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
use crate::deriving::generic::ty::*;
|
||||
|
|
|
|||
|
|
@ -6,12 +6,11 @@ use rustc_ast::{
|
|||
self as ast, GenericArg, GenericBound, GenericParamKind, ItemKind, MetaItem,
|
||||
TraitBoundModifiers, VariantData, WherePredicate,
|
||||
};
|
||||
use rustc_attr as attr;
|
||||
use rustc_attr_parsing as attr;
|
||||
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_macros::Diagnostic;
|
||||
use rustc_span::symbol::{Ident, sym};
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_span::{Ident, Span, Symbol, sym};
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
|
||||
use crate::errors;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
use rustc_ast::{self as ast, EnumDef, MetaItem};
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_session::config::FmtDebug;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::{Ident, Symbol, sym};
|
||||
use rustc_span::{Ident, Span, Symbol, sym};
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
|
||||
use crate::deriving::generic::ty::*;
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@
|
|||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{self as ast, Expr, MetaItem, Mutability};
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::{Ident, Symbol, sym};
|
||||
use rustc_span::{Ident, Span, Symbol, sym};
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
|
||||
use crate::deriving::generic::ty::*;
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@ use rustc_ast as ast;
|
|||
use rustc_ast::visit::visit_opt;
|
||||
use rustc_ast::{EnumDef, VariantData, attr};
|
||||
use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt};
|
||||
use rustc_span::symbol::{Ident, kw, sym};
|
||||
use rustc_span::{ErrorGuaranteed, Span};
|
||||
use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym};
|
||||
use smallvec::SmallVec;
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
|
||||
|
|
|
|||
|
|
@ -87,8 +87,7 @@
|
|||
|
||||
use rustc_ast::{AttrVec, ExprKind, MetaItem, Mutability};
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::{Ident, Symbol, sym};
|
||||
use rustc_span::{Ident, Span, Symbol, sym};
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
|
||||
use crate::deriving::generic::ty::*;
|
||||
|
|
|
|||
|
|
@ -185,10 +185,9 @@ use rustc_ast::{
|
|||
self as ast, AnonConst, BindingMode, ByRef, EnumDef, Expr, GenericArg, GenericParamKind,
|
||||
Generics, Mutability, PatKind, VariantData,
|
||||
};
|
||||
use rustc_attr as attr;
|
||||
use rustc_attr_parsing as attr;
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::symbol::{Ident, Symbol, kw, sym};
|
||||
use rustc_span::{DUMMY_SP, Span};
|
||||
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
use ty::{Bounds, Path, Ref, Self_, Ty};
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@ use rustc_ast::ptr::P;
|
|||
use rustc_ast::{self as ast, Expr, GenericArg, GenericParamKind, Generics, SelfKind};
|
||||
use rustc_expand::base::ExtCtxt;
|
||||
use rustc_span::source_map::respan;
|
||||
use rustc_span::symbol::{Ident, Symbol, kw};
|
||||
use rustc_span::{DUMMY_SP, Span};
|
||||
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw};
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
/// A path, e.g., `::std::option::Option::<i32>` (global). Has support
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use rustc_ast::{MetaItem, Mutability};
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{Span, sym};
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
use crate::deriving::generic::ty::*;
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@ use rustc_ast as ast;
|
|||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::{GenericArg, MetaItem};
|
||||
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::{Symbol, sym};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
|
||||
macro path_local($x:ident) {
|
||||
|
|
|
|||
|
|
@ -3,9 +3,8 @@ use rustc_ast::token::Delimiter;
|
|||
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
|
||||
use rustc_ast::*;
|
||||
use rustc_expand::base::*;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{Span, sym};
|
||||
|
||||
/// This expands to either
|
||||
/// - `$crate::panic::panic_2015!(...)` or
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ use rustc_ast::token::{self, LitKind};
|
|||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::{AstDeref, ExprKind, GenericArg, Mutability};
|
||||
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::{Ident, Symbol, kw, sym};
|
||||
use rustc_span::{Ident, Span, Symbol, kw, sym};
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
use crate::errors;
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@ use rustc_errors::{
|
|||
SubdiagMessageOp, Subdiagnostic,
|
||||
};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_span::{Ident, Span, Symbol};
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_requires_cfg_pattern)]
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue