Merge pull request #4097 from rust-lang/rustup-2024-12-18

Automatic Rustup
This commit is contained in:
Oli Scherer 2024-12-18 05:28:59 +00:00 committed by GitHub
commit 955ef09831
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
923 changed files with 22139 additions and 8889 deletions

View file

@ -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).

View file

@ -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",

View file

@ -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;

View file

@ -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,

View file

@ -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)
}
}

View file

@ -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 {

View file

@ -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 {

View file

@ -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;

View file

@ -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;

View file

@ -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 {}

View file

@ -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);
}
}

View file

@ -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;

View file

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

View file

@ -1,4 +1,4 @@
use rustc_span::symbol::kw;
use rustc_span::kw;
use crate::ast::{self, BinOpKind};
use crate::token::{self, BinOpToken, Token};

View file

@ -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()
}

View file

@ -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;

View file

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

View file

@ -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)]

View file

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

View file

@ -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;

View file

@ -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,

View file

@ -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>,

View file

@ -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");

View file

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

View file

@ -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" }

View file

@ -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() {

View file

@ -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;

View file

@ -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;

View file

@ -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();

View file

@ -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;

View file

@ -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

View file

@ -1,5 +1,5 @@
[package]
name = "rustc_attr"
name = "rustc_attr_data_structures"
version = "0.0.0"
edition = "2021"

View 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(_))
}
}

View 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::*;

View 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),
}
}
}

View file

@ -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()))
}
}

View 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

View file

@ -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

View 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
})
}

View 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,
})
}
}
}

View 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)
}

View 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
}

View 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::*;

View 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")
}
}

View 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,
}
}

View 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)
}

View 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 })
}

View file

@ -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" }

View file

@ -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,

View file

@ -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;

View file

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

View file

@ -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::{

View file

@ -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.

View file

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

View file

@ -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()) {

View file

@ -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;

View file

@ -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, &regioncx, &opt_closure_req, &opaque_type_values, diags);
let movable_coroutine =

View file

@ -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(

View 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)));
}
_ => {}
}
}
}

View file

@ -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) {

View file

@ -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));
}
}
}

View 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)
}),
)
}
},
));
}

View file

@ -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;

View file

@ -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

View file

@ -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,

View file

@ -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()));
});
}
}

View file

@ -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,
);
}
}

View file

@ -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() })
}

View file

@ -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;

View file

@ -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;

View file

@ -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" }

View file

@ -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;

View file

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

View file

@ -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;

View file

@ -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> {

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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::*;

View file

@ -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::*;

View file

@ -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::*;

View file

@ -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::*;

View file

@ -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::*;

View file

@ -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;

View file

@ -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::*;

View file

@ -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::*;

View file

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

View file

@ -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::*;

View file

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

View file

@ -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

View file

@ -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::*;

View file

@ -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) {

View file

@ -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

View file

@ -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;

View file

@ -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