Merge pull request #4820 from rust-lang/rustup-2026-01-20
Automatic Rustup
This commit is contained in:
commit
0aac6d1367
709 changed files with 7887 additions and 3806 deletions
1
.github/ISSUE_TEMPLATE/ice.md
vendored
1
.github/ISSUE_TEMPLATE/ice.md
vendored
|
|
@ -2,6 +2,7 @@
|
|||
name: Internal Compiler Error
|
||||
about: Create a report for an internal compiler error in rustc.
|
||||
labels: C-bug, I-ICE, T-compiler
|
||||
title: "[ICE]: "
|
||||
---
|
||||
<!--
|
||||
Thank you for finding an Internal Compiler Error! 🧊 If possible, try to provide
|
||||
|
|
|
|||
16
.github/workflows/ci.yml
vendored
16
.github/workflows/ci.yml
vendored
|
|
@ -305,30 +305,22 @@ jobs:
|
|||
DD_GITHUB_JOB_NAME: ${{ matrix.full_name }}
|
||||
run: ./build/citool/debug/citool upload-build-metrics 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).
|
||||
# This job is used to publish toolstate for successful auto builds.
|
||||
outcome:
|
||||
name: bors build finished
|
||||
name: publish toolstate
|
||||
runs-on: ubuntu-24.04
|
||||
needs: [ calculate_matrix, job ]
|
||||
# !cancelled() executes the job regardless of whether the previous jobs passed or failed
|
||||
if: ${{ !cancelled() && contains(fromJSON('["auto", "try"]'), needs.calculate_matrix.outputs.run_type) }}
|
||||
environment: ${{ ((github.repository == 'rust-lang/rust' && (github.ref == 'refs/heads/try-perf' || github.ref == 'refs/heads/automation/bors/try' || github.ref == 'refs/heads/automation/bors/auto')) && 'bors') || '' }}
|
||||
if: ${{ needs.calculate_matrix.outputs.run_type == 'auto' }}
|
||||
environment: ${{ (github.repository == 'rust-lang/rust' && 'bors') || '' }}
|
||||
steps:
|
||||
- name: checkout the source code
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 2
|
||||
# Calculate the exit status of the whole CI workflow.
|
||||
# If all dependent jobs were successful, this exits with 0 (and the outcome job continues successfully).
|
||||
# If a some dependent job has failed, this exits with 1.
|
||||
- name: calculate the correct exit status
|
||||
run: jq --exit-status 'all(.result == "success" or .result == "skipped")' <<< '${{ toJson(needs) }}'
|
||||
# Publish the toolstate if an auto build succeeds (just before push to the default branch)
|
||||
- name: publish toolstate
|
||||
run: src/ci/publish_toolstate.sh
|
||||
shell: bash
|
||||
if: needs.calculate_matrix.outputs.run_type == 'auto'
|
||||
env:
|
||||
TOOLSTATE_ISSUES_API_URL: https://api.github.com/repos/rust-lang/rust/issues
|
||||
TOOLSTATE_PUBLISH: 1
|
||||
|
|
|
|||
16
.github/workflows/dependencies.yml
vendored
16
.github/workflows/dependencies.yml
vendored
|
|
@ -62,19 +62,9 @@ jobs:
|
|||
rustup toolchain install --no-self-update --profile minimal $TOOLCHAIN
|
||||
rustup default $TOOLCHAIN
|
||||
|
||||
- name: cargo update compiler & tools
|
||||
# Remove first line that always just says "Updating crates.io index"
|
||||
run: |
|
||||
echo -e "\ncompiler & tools dependencies:" >> cargo_update.log
|
||||
cargo update 2>&1 | sed '/crates.io index/d' | tee -a cargo_update.log
|
||||
- name: cargo update library
|
||||
run: |
|
||||
echo -e "\nlibrary dependencies:" >> cargo_update.log
|
||||
cargo update --manifest-path library/Cargo.toml 2>&1 | sed '/crates.io index/d' | tee -a cargo_update.log
|
||||
- name: cargo update rustbook
|
||||
run: |
|
||||
echo -e "\nrustbook dependencies:" >> cargo_update.log
|
||||
cargo update --manifest-path src/tools/rustbook/Cargo.toml 2>&1 | sed '/crates.io index/d' | tee -a cargo_update.log
|
||||
- name: cargo update
|
||||
run: ./src/tools/update-lockfile.sh
|
||||
|
||||
- name: upload Cargo.lock artifact for use in PR
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
|
|
|
|||
|
|
@ -3767,6 +3767,7 @@ dependencies = [
|
|||
name = "rustc_driver_impl"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"ctrlc",
|
||||
"jiff",
|
||||
"libc",
|
||||
|
|
@ -3792,6 +3793,7 @@ dependencies = [
|
|||
"rustc_index",
|
||||
"rustc_infer",
|
||||
"rustc_interface",
|
||||
"rustc_lexer",
|
||||
"rustc_lint",
|
||||
"rustc_log",
|
||||
"rustc_macros",
|
||||
|
|
@ -3887,11 +3889,13 @@ dependencies = [
|
|||
"rustc_lexer",
|
||||
"rustc_lint_defs",
|
||||
"rustc_macros",
|
||||
"rustc_middle",
|
||||
"rustc_parse",
|
||||
"rustc_proc_macro",
|
||||
"rustc_serialize",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
"scoped-tls",
|
||||
"smallvec",
|
||||
"thin-vec",
|
||||
"tracing",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use std::assert_matches::assert_matches;
|
||||
use std::str::FromStr;
|
||||
|
||||
use rustc_data_structures::assert_matches;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
|
|
|
|||
|
|
@ -3348,7 +3348,8 @@ impl UseTree {
|
|||
/// Distinguishes between `Attribute`s that decorate items and Attributes that
|
||||
/// are contained as statements within items. These two cases need to be
|
||||
/// distinguished for pretty-printing.
|
||||
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy, HashStable_Generic, Walkable)]
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug, Copy)]
|
||||
#[derive(Encodable, Decodable, HashStable_Generic, Walkable)]
|
||||
pub enum AttrStyle {
|
||||
Outer,
|
||||
Inner,
|
||||
|
|
|
|||
|
|
@ -40,13 +40,13 @@ impl DocFragmentKind {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
pub enum CommentKind {
|
||||
Line,
|
||||
Block,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug, Encodable, Decodable, HashStable_Generic)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable, HashStable_Generic)]
|
||||
pub enum InvisibleOrigin {
|
||||
// From the expansion of a metavariable in a declarative macro.
|
||||
MetaVar(MetaVarKind),
|
||||
|
|
@ -123,7 +123,7 @@ impl fmt::Display for MetaVarKind {
|
|||
/// Describes how a sequence of token trees is delimited.
|
||||
/// Cannot use `proc_macro::Delimiter` directly because this
|
||||
/// structure should implement some additional traits.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)]
|
||||
pub enum Delimiter {
|
||||
/// `( ... )`
|
||||
Parenthesis,
|
||||
|
|
@ -186,7 +186,7 @@ impl Delimiter {
|
|||
// type. This means that float literals like `1f32` are classified by this type
|
||||
// as `Int`. Only upon conversion to `ast::LitKind` will such a literal be
|
||||
// given the `Float` kind.
|
||||
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
pub enum LitKind {
|
||||
Bool, // AST only, must never appear in a `Token`
|
||||
Byte,
|
||||
|
|
@ -203,7 +203,7 @@ pub enum LitKind {
|
|||
}
|
||||
|
||||
/// A literal token.
|
||||
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
pub struct Lit {
|
||||
pub kind: LitKind,
|
||||
pub symbol: Symbol,
|
||||
|
|
@ -349,7 +349,7 @@ fn ident_can_begin_type(name: Symbol, span: Span, is_raw: IdentIsRaw) -> bool {
|
|||
.contains(&name)
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Encodable, Decodable, Debug, Copy, Clone, HashStable_Generic)]
|
||||
#[derive(PartialEq, Eq, Encodable, Decodable, Hash, Debug, Copy, Clone, HashStable_Generic)]
|
||||
pub enum IdentIsRaw {
|
||||
No,
|
||||
Yes,
|
||||
|
|
@ -376,7 +376,7 @@ impl From<bool> for IdentIsRaw {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
pub enum TokenKind {
|
||||
/* Expression-operator symbols. */
|
||||
/// `=`
|
||||
|
|
@ -526,7 +526,7 @@ pub enum TokenKind {
|
|||
Eof,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, Debug, HashStable_Generic)]
|
||||
pub struct Token {
|
||||
pub kind: TokenKind,
|
||||
pub span: Span,
|
||||
|
|
@ -625,12 +625,12 @@ impl TokenKind {
|
|||
}
|
||||
|
||||
impl Token {
|
||||
pub fn new(kind: TokenKind, span: Span) -> Self {
|
||||
pub const fn new(kind: TokenKind, span: Span) -> Self {
|
||||
Token { kind, span }
|
||||
}
|
||||
|
||||
/// Some token that will be thrown away later.
|
||||
pub fn dummy() -> Self {
|
||||
pub const fn dummy() -> Self {
|
||||
Token::new(TokenKind::Question, DUMMY_SP)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
//! which are themselves a single [`Token`] or a `Delimited` subsequence of tokens.
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::hash::Hash;
|
||||
use std::ops::Range;
|
||||
use std::sync::Arc;
|
||||
use std::{cmp, fmt, iter, mem};
|
||||
|
|
@ -22,7 +23,7 @@ use crate::token::{self, Delimiter, Token, TokenKind};
|
|||
use crate::{AttrVec, Attribute};
|
||||
|
||||
/// Part of a `TokenStream`.
|
||||
#[derive(Debug, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)]
|
||||
pub enum TokenTree {
|
||||
/// A single token. Should never be `OpenDelim` or `CloseDelim`, because
|
||||
/// delimiters are implicitly represented by `Delimited`.
|
||||
|
|
@ -538,7 +539,7 @@ pub struct AttrsTarget {
|
|||
/// compound token. Used for conversions to `proc_macro::Spacing`. Also used to
|
||||
/// guide pretty-printing, which is where the `JointHidden` value (which isn't
|
||||
/// part of `proc_macro::Spacing`) comes in useful.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)]
|
||||
pub enum Spacing {
|
||||
/// The token cannot join with the following token to form a compound
|
||||
/// token.
|
||||
|
|
@ -595,7 +596,7 @@ pub enum Spacing {
|
|||
}
|
||||
|
||||
/// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s.
|
||||
#[derive(Clone, Debug, Default, Encodable, Decodable)]
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Encodable, Decodable)]
|
||||
pub struct TokenStream(pub(crate) Arc<Vec<TokenTree>>);
|
||||
|
||||
impl TokenStream {
|
||||
|
|
@ -811,14 +812,6 @@ impl TokenStream {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialEq<TokenStream> for TokenStream {
|
||||
fn eq(&self, other: &TokenStream) -> bool {
|
||||
self.iter().eq(other.iter())
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for TokenStream {}
|
||||
|
||||
impl FromIterator<TokenTree> for TokenStream {
|
||||
fn from_iter<I: IntoIterator<Item = TokenTree>>(iter: I) -> Self {
|
||||
TokenStream::new(iter.into_iter().collect::<Vec<TokenTree>>())
|
||||
|
|
@ -970,7 +963,8 @@ impl TokenCursor {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic, Walkable)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
#[derive(Encodable, Decodable, HashStable_Generic, Walkable)]
|
||||
pub struct DelimSpan {
|
||||
pub open: Span,
|
||||
pub close: Span,
|
||||
|
|
@ -994,7 +988,7 @@ impl DelimSpan {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)]
|
||||
pub struct DelimSpacing {
|
||||
pub open: Spacing,
|
||||
pub close: Spacing,
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ use rustc_hir::attrs::AttributeKind;
|
|||
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
|
||||
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
|
||||
use rustc_hir::definitions::{DefPathData, DisambiguatorState};
|
||||
use rustc_hir::lints::DelayedLint;
|
||||
use rustc_hir::lints::{AttributeLint, DelayedLint};
|
||||
use rustc_hir::{
|
||||
self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LifetimeSource,
|
||||
LifetimeSyntax, ParamName, Target, TraitCandidate, find_attr,
|
||||
|
|
@ -1022,12 +1022,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
self.attribute_parser.parse_attribute_list(
|
||||
attrs,
|
||||
target_span,
|
||||
target_hir_id,
|
||||
target,
|
||||
OmitDoc::Lower,
|
||||
|s| l.lower(s),
|
||||
|l| {
|
||||
self.delayed_lints.push(DelayedLint::AttributeParsing(l));
|
||||
|lint_id, span, kind| {
|
||||
self.delayed_lints.push(DelayedLint::AttributeParsing(AttributeLint {
|
||||
lint_id,
|
||||
id: target_hir_id,
|
||||
span,
|
||||
kind,
|
||||
}));
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
@ -2380,7 +2384,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
Some(ConstItemRhs::TypeConst(anon)) => {
|
||||
hir::ConstItemRhs::TypeConst(self.lower_anon_const_to_const_arg_and_alloc(anon))
|
||||
}
|
||||
None if attr::contains_name(attrs, sym::type_const) => {
|
||||
None if find_attr!(attrs, AttributeKind::TypeConst(_)) => {
|
||||
let const_arg = ConstArg {
|
||||
hir_id: self.next_id(),
|
||||
kind: hir::ConstArgKind::Error(
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ pub(crate) fn extern_abi_enabled(
|
|||
})
|
||||
}
|
||||
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
pub(crate) fn gate_unstable_abi(sess: &Session, features: &Features, span: Span, abi: ExternAbi) {
|
||||
match extern_abi_enabled(features, span, abi) {
|
||||
Ok(_) => (),
|
||||
|
|
|
|||
|
|
@ -13,15 +13,11 @@ use crate::errors;
|
|||
macro_rules! gate {
|
||||
($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
|
||||
if !$visitor.features.$feature() && !$span.allows_unstable(sym::$feature) {
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
feature_err(&$visitor.sess, sym::$feature, $span, $explain).emit();
|
||||
}
|
||||
}};
|
||||
($visitor:expr, $feature:ident, $span:expr, $explain:expr, $help:expr) => {{
|
||||
if !$visitor.features.$feature() && !$span.allows_unstable(sym::$feature) {
|
||||
// FIXME: make this translatable
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
feature_err(&$visitor.sess, sym::$feature, $span, $explain).with_help($help).emit();
|
||||
}
|
||||
}};
|
||||
|
|
@ -31,13 +27,11 @@ macro_rules! gate {
|
|||
macro_rules! gate_alt {
|
||||
($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr) => {{
|
||||
if !$has_feature && !$span.allows_unstable($name) {
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
feature_err(&$visitor.sess, $name, $span, $explain).emit();
|
||||
}
|
||||
}};
|
||||
($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr, $notes: expr) => {{
|
||||
if !$has_feature && !$span.allows_unstable($name) {
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
let mut diag = feature_err(&$visitor.sess, $name, $span, $explain);
|
||||
for note in $notes {
|
||||
diag.note(*note);
|
||||
|
|
@ -491,7 +485,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||
&& (!visitor.features.gen_blocks() && !span.allows_unstable(sym::gen_blocks))
|
||||
&& (!visitor.features.yield_expr() && !span.allows_unstable(sym::yield_expr))
|
||||
{
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
// Emit yield_expr as the error, since that will be sufficient. You can think of it
|
||||
// as coroutines and gen_blocks imply yield_expr.
|
||||
feature_err(&visitor.sess, sym::yield_expr, *span, "yield syntax is experimental")
|
||||
|
|
@ -523,7 +516,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||
if !visitor.features.min_generic_const_args()
|
||||
&& !span.allows_unstable(sym::min_generic_const_args)
|
||||
{
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
feature_err(
|
||||
&visitor.sess,
|
||||
sym::min_generic_const_args,
|
||||
|
|
@ -559,7 +551,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||
if let Ok(snippet) = sm.span_to_snippet(span)
|
||||
&& snippet == "!"
|
||||
{
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
feature_err(sess, sym::never_patterns, span, "`!` patterns are experimental")
|
||||
.emit();
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ attr_parsing_unstable_cfg_target_compact =
|
|||
compact `cfg(target(..))` is experimental and subject to change
|
||||
|
||||
attr_parsing_unstable_feature_bound_incompatible_stability = item annotated with `#[unstable_feature_bound]` should not be stable
|
||||
.help = If this item is meant to be stable, do not use any functions annotated with `#[unstable_feature_bound]`. Otherwise, mark this item as unstable with `#[unstable]`
|
||||
.help = if this item is meant to be stable, do not use any functions annotated with `#[unstable_feature_bound]`. Otherwise, mark this item as unstable with `#[unstable]`
|
||||
|
||||
attr_parsing_unsupported_instruction_set = target `{$current_target}` does not support `#[instruction_set({$instruction_set}::*)]`
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use rustc_feature::{
|
|||
};
|
||||
use rustc_hir::attrs::CfgEntry;
|
||||
use rustc_hir::lints::AttributeLintKind;
|
||||
use rustc_hir::{AttrPath, RustcVersion};
|
||||
use rustc_hir::{AttrPath, RustcVersion, Target};
|
||||
use rustc_parse::parser::{ForceCollect, Parser};
|
||||
use rustc_parse::{exp, parse_in};
|
||||
use rustc_session::Session;
|
||||
|
|
@ -373,6 +373,7 @@ fn parse_cfg_attr_internal<'a>(
|
|||
ParsedDescription::Attribute,
|
||||
pred_span,
|
||||
CRATE_NODE_ID,
|
||||
Target::Crate,
|
||||
features,
|
||||
ShouldEmit::ErrorsAndLints,
|
||||
&meta,
|
||||
|
|
@ -411,7 +412,6 @@ fn try_gate_cfg(name: Symbol, span: Span, sess: &Session, features: Option<&Feat
|
|||
}
|
||||
}
|
||||
|
||||
#[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) {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ use rustc_ast::token::Token;
|
|||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::{AttrStyle, NodeId, token};
|
||||
use rustc_feature::{AttributeTemplate, Features};
|
||||
use rustc_hir::AttrPath;
|
||||
use rustc_hir::attrs::CfgEntry;
|
||||
use rustc_hir::{AttrPath, Target};
|
||||
use rustc_parse::exp;
|
||||
use rustc_parse::parser::Parser;
|
||||
use rustc_session::Session;
|
||||
|
|
@ -91,6 +91,8 @@ pub fn parse_cfg_select(
|
|||
ParsedDescription::Macro,
|
||||
cfg_span,
|
||||
lint_node_id,
|
||||
// Doesn't matter what the target actually is here.
|
||||
Target::Crate,
|
||||
features,
|
||||
ShouldEmit::ErrorsAndLints,
|
||||
&meta,
|
||||
|
|
|
|||
|
|
@ -136,6 +136,15 @@ impl<S: Stage> NoArgsAttributeParser<S> for NoStdParser {
|
|||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoStd;
|
||||
}
|
||||
|
||||
pub(crate) struct NoMainParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for NoMainParser {
|
||||
const PATH: &[Symbol] = &[sym::no_main];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoMain;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcCoherenceIsCoreParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcCoherenceIsCoreParser {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
use rustc_feature::{AttributeTemplate, template};
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::lints::AttributeLintKind;
|
||||
use rustc_session::lint::builtin::MALFORMED_DIAGNOSTIC_ATTRIBUTES;
|
||||
use rustc_span::{Symbol, sym};
|
||||
|
||||
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
|
||||
use crate::context::{AcceptContext, Stage};
|
||||
use crate::parser::ArgParser;
|
||||
use crate::target_checking::{ALL_TARGETS, AllowedTargets};
|
||||
|
||||
pub(crate) struct DoNotRecommendParser;
|
||||
impl<S: Stage> SingleAttributeParser<S> for DoNotRecommendParser {
|
||||
const PATH: &[Symbol] = &[sym::diagnostic, sym::do_not_recommend];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); // Checked in check_attr.
|
||||
const TEMPLATE: AttributeTemplate = template!(Word /*doesn't matter */);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
|
||||
let attr_span = cx.attr_span;
|
||||
if !matches!(args, ArgParser::NoArgs) {
|
||||
cx.emit_lint(
|
||||
MALFORMED_DIAGNOSTIC_ATTRIBUTES,
|
||||
AttributeLintKind::DoNotRecommendDoesNotExpectArgs,
|
||||
attr_span,
|
||||
);
|
||||
}
|
||||
Some(AttributeKind::DoNotRecommend { attr_span })
|
||||
}
|
||||
}
|
||||
|
|
@ -50,7 +50,7 @@ fn check_attr_not_crate_level<S: Stage>(
|
|||
span: Span,
|
||||
attr_name: Symbol,
|
||||
) -> bool {
|
||||
if cx.shared.target.is_some_and(|target| target == Target::Crate) {
|
||||
if cx.shared.target == Target::Crate {
|
||||
cx.emit_err(DocAttrNotCrateLevel { span, attr_name });
|
||||
return false;
|
||||
}
|
||||
|
|
@ -59,7 +59,7 @@ fn check_attr_not_crate_level<S: Stage>(
|
|||
|
||||
/// Checks that an attribute is used at the crate level. Returns `true` if valid.
|
||||
fn check_attr_crate_level<S: Stage>(cx: &mut AcceptContext<'_, '_, S>, span: Span) -> bool {
|
||||
if cx.shared.target.is_some_and(|target| target != Target::Crate) {
|
||||
if cx.shared.target != Target::Crate {
|
||||
cx.emit_lint(
|
||||
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
||||
AttributeLintKind::AttrCrateLevelOnly,
|
||||
|
|
|
|||
|
|
@ -141,8 +141,6 @@ impl<S: Stage> CombineAttributeParser<S> for LinkParser {
|
|||
|
||||
macro report_unstable_modifier($feature: ident) {
|
||||
if !features.$feature() {
|
||||
// FIXME: make this translatable
|
||||
#[expect(rustc::untranslatable_diagnostic)]
|
||||
feature_err(
|
||||
sess,
|
||||
sym::$feature,
|
||||
|
|
@ -658,3 +656,12 @@ impl<S: Stage> SingleAttributeParser<S> for LinkageParser {
|
|||
Some(AttributeKind::Linkage(linkage, cx.attr_span))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct NeedsAllocatorParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for NeedsAllocatorParser {
|
||||
const PATH: &[Symbol] = &[sym::needs_allocator];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NeedsAllocator;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ pub(crate) mod confusables;
|
|||
pub(crate) mod crate_level;
|
||||
pub(crate) mod debugger;
|
||||
pub(crate) mod deprecation;
|
||||
pub(crate) mod do_not_recommend;
|
||||
pub(crate) mod doc;
|
||||
pub(crate) mod dummy;
|
||||
pub(crate) mod inline;
|
||||
|
|
@ -57,6 +58,7 @@ pub(crate) mod pin_v2;
|
|||
pub(crate) mod proc_macro_attrs;
|
||||
pub(crate) mod prototype;
|
||||
pub(crate) mod repr;
|
||||
pub(crate) mod rustc_allocator;
|
||||
pub(crate) mod rustc_dump;
|
||||
pub(crate) mod rustc_internal;
|
||||
pub(crate) mod semantics;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
use super::prelude::*;
|
||||
|
||||
pub(crate) struct RustcAllocatorParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcAllocatorParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_allocator];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets =
|
||||
AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcAllocator;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcAllocatorZeroedParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcAllocatorZeroedParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_allocator_zeroed];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets =
|
||||
AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcAllocatorZeroed;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcAllocatorZeroedVariantParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcAllocatorZeroedVariantParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_allocator_zeroed_variant];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets =
|
||||
AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]);
|
||||
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "function");
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
|
||||
let Some(name) = args.name_value().and_then(NameValueParser::value_as_str) else {
|
||||
cx.expected_name_value(cx.attr_span, None);
|
||||
return None;
|
||||
};
|
||||
|
||||
Some(AttributeKind::RustcAllocatorZeroedVariant { name })
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct RustcDeallocatorParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcDeallocatorParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_deallocator];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets =
|
||||
AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDeallocator;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcReallocatorParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcReallocatorParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_reallocator];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets =
|
||||
AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcReallocator;
|
||||
}
|
||||
|
|
@ -164,21 +164,6 @@ impl<S: Stage> SingleAttributeParser<S> for RustcLegacyConstGenericsParser {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) struct RustcLintDiagnosticsParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcLintDiagnosticsParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_lint_diagnostics];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Fn),
|
||||
Allow(Target::Method(MethodKind::Inherent)),
|
||||
Allow(Target::Method(MethodKind::Trait { body: false })),
|
||||
Allow(Target::Method(MethodKind::Trait { body: true })),
|
||||
Allow(Target::Method(MethodKind::TraitImpl)),
|
||||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintDiagnostics;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcLintOptDenyFieldAccessParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcLintOptDenyFieldAccessParser {
|
||||
|
|
@ -320,3 +305,27 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcHasIncoherentInherentImplsParse
|
|||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcHasIncoherentInherentImpls;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcNounwindParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcNounwindParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_nounwind];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
|
||||
Allow(Target::Fn),
|
||||
Allow(Target::ForeignFn),
|
||||
Allow(Target::Method(MethodKind::Inherent)),
|
||||
Allow(Target::Method(MethodKind::TraitImpl)),
|
||||
Allow(Target::Method(MethodKind::Trait { body: true })),
|
||||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNounwind;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcOffloadKernelParser;
|
||||
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcOffloadKernelParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_offload_kernel];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcOffloadKernel;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,6 @@ use super::prelude::*;
|
|||
|
||||
pub(crate) struct TransparencyParser;
|
||||
|
||||
// FIXME(jdonszelmann): make these proper diagnostics
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
impl<S: Stage> SingleAttributeParser<S> for TransparencyParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_macro_transparency];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use rustc_ast::{AttrStyle, MetaItemLit, NodeId};
|
|||
use rustc_errors::{Diag, Diagnostic, Level};
|
||||
use rustc_feature::{AttrSuggestionStyle, AttributeTemplate};
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::lints::{AttributeLint, AttributeLintKind};
|
||||
use rustc_hir::lints::AttributeLintKind;
|
||||
use rustc_hir::{AttrPath, HirId};
|
||||
use rustc_session::Session;
|
||||
use rustc_session::lint::{Lint, LintId};
|
||||
|
|
@ -28,19 +28,20 @@ use crate::attributes::codegen_attrs::{
|
|||
};
|
||||
use crate::attributes::confusables::ConfusablesParser;
|
||||
use crate::attributes::crate_level::{
|
||||
CrateNameParser, MoveSizeLimitParser, NoCoreParser, NoStdParser, PatternComplexityLimitParser,
|
||||
RecursionLimitParser, RustcCoherenceIsCoreParser, TypeLengthLimitParser,
|
||||
WindowsSubsystemParser,
|
||||
CrateNameParser, MoveSizeLimitParser, NoCoreParser, NoMainParser, NoStdParser,
|
||||
PatternComplexityLimitParser, RecursionLimitParser, RustcCoherenceIsCoreParser,
|
||||
TypeLengthLimitParser, WindowsSubsystemParser,
|
||||
};
|
||||
use crate::attributes::debugger::DebuggerViualizerParser;
|
||||
use crate::attributes::deprecation::DeprecationParser;
|
||||
use crate::attributes::do_not_recommend::DoNotRecommendParser;
|
||||
use crate::attributes::doc::DocParser;
|
||||
use crate::attributes::dummy::DummyParser;
|
||||
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
|
||||
use crate::attributes::instruction_set::InstructionSetParser;
|
||||
use crate::attributes::link_attrs::{
|
||||
ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkOrdinalParser,
|
||||
LinkParser, LinkSectionParser, LinkageParser, StdInternalSymbolParser,
|
||||
LinkParser, LinkSectionParser, LinkageParser, NeedsAllocatorParser, StdInternalSymbolParser,
|
||||
};
|
||||
use crate::attributes::lint_helpers::{
|
||||
AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser,
|
||||
|
|
@ -63,6 +64,10 @@ use crate::attributes::proc_macro_attrs::{
|
|||
};
|
||||
use crate::attributes::prototype::CustomMirParser;
|
||||
use crate::attributes::repr::{AlignParser, AlignStaticParser, ReprParser};
|
||||
use crate::attributes::rustc_allocator::{
|
||||
RustcAllocatorParser, RustcAllocatorZeroedParser, RustcAllocatorZeroedVariantParser,
|
||||
RustcDeallocatorParser, RustcReallocatorParser,
|
||||
};
|
||||
use crate::attributes::rustc_dump::{
|
||||
RustcDumpDefParents, RustcDumpItemBounds, RustcDumpPredicates, RustcDumpUserArgs,
|
||||
RustcDumpVtable,
|
||||
|
|
@ -70,10 +75,10 @@ use crate::attributes::rustc_dump::{
|
|||
use crate::attributes::rustc_internal::{
|
||||
RustcHasIncoherentInherentImplsParser, RustcLayoutScalarValidRangeEndParser,
|
||||
RustcLayoutScalarValidRangeStartParser, RustcLegacyConstGenericsParser,
|
||||
RustcLintDiagnosticsParser, RustcLintOptDenyFieldAccessParser, RustcLintOptTyParser,
|
||||
RustcLintQueryInstabilityParser, RustcLintUntrackedQueryInformationParser, RustcMainParser,
|
||||
RustcMustImplementOneOfParser, RustcNeverReturnsNullPointerParser,
|
||||
RustcNoImplicitAutorefsParser, RustcObjectLifetimeDefaultParser, RustcScalableVectorParser,
|
||||
RustcLintOptDenyFieldAccessParser, RustcLintOptTyParser, RustcLintQueryInstabilityParser,
|
||||
RustcLintUntrackedQueryInformationParser, RustcMainParser, RustcMustImplementOneOfParser,
|
||||
RustcNeverReturnsNullPointerParser, RustcNoImplicitAutorefsParser, RustcNounwindParser,
|
||||
RustcObjectLifetimeDefaultParser, RustcOffloadKernelParser, RustcScalableVectorParser,
|
||||
RustcSimdMonomorphizeLaneLimitParser,
|
||||
};
|
||||
use crate::attributes::semantics::MayDangleParser;
|
||||
|
|
@ -201,6 +206,7 @@ attribute_parsers!(
|
|||
Single<CrateNameParser>,
|
||||
Single<CustomMirParser>,
|
||||
Single<DeprecationParser>,
|
||||
Single<DoNotRecommendParser>,
|
||||
Single<DummyParser>,
|
||||
Single<ExportNameParser>,
|
||||
Single<IgnoreParser>,
|
||||
|
|
@ -221,6 +227,7 @@ attribute_parsers!(
|
|||
Single<PatternComplexityLimitParser>,
|
||||
Single<ProcMacroDeriveParser>,
|
||||
Single<RecursionLimitParser>,
|
||||
Single<RustcAllocatorZeroedVariantParser>,
|
||||
Single<RustcBuiltinMacroParser>,
|
||||
Single<RustcForceInlineParser>,
|
||||
Single<RustcLayoutScalarValidRangeEndParser>,
|
||||
|
|
@ -257,9 +264,11 @@ attribute_parsers!(
|
|||
Single<WithoutArgs<MacroEscapeParser>>,
|
||||
Single<WithoutArgs<MarkerParser>>,
|
||||
Single<WithoutArgs<MayDangleParser>>,
|
||||
Single<WithoutArgs<NeedsAllocatorParser>>,
|
||||
Single<WithoutArgs<NoCoreParser>>,
|
||||
Single<WithoutArgs<NoImplicitPreludeParser>>,
|
||||
Single<WithoutArgs<NoLinkParser>>,
|
||||
Single<WithoutArgs<NoMainParser>>,
|
||||
Single<WithoutArgs<NoMangleParser>>,
|
||||
Single<WithoutArgs<NoStdParser>>,
|
||||
Single<WithoutArgs<NonExhaustiveParser>>,
|
||||
|
|
@ -270,21 +279,26 @@ attribute_parsers!(
|
|||
Single<WithoutArgs<ProcMacroAttributeParser>>,
|
||||
Single<WithoutArgs<ProcMacroParser>>,
|
||||
Single<WithoutArgs<PubTransparentParser>>,
|
||||
Single<WithoutArgs<RustcAllocatorParser>>,
|
||||
Single<WithoutArgs<RustcAllocatorZeroedParser>>,
|
||||
Single<WithoutArgs<RustcCoherenceIsCoreParser>>,
|
||||
Single<WithoutArgs<RustcDeallocatorParser>>,
|
||||
Single<WithoutArgs<RustcDumpDefParents>>,
|
||||
Single<WithoutArgs<RustcDumpItemBounds>>,
|
||||
Single<WithoutArgs<RustcDumpPredicates>>,
|
||||
Single<WithoutArgs<RustcDumpUserArgs>>,
|
||||
Single<WithoutArgs<RustcDumpVtable>>,
|
||||
Single<WithoutArgs<RustcHasIncoherentInherentImplsParser>>,
|
||||
Single<WithoutArgs<RustcLintDiagnosticsParser>>,
|
||||
Single<WithoutArgs<RustcLintOptTyParser>>,
|
||||
Single<WithoutArgs<RustcLintQueryInstabilityParser>>,
|
||||
Single<WithoutArgs<RustcLintUntrackedQueryInformationParser>>,
|
||||
Single<WithoutArgs<RustcMainParser>>,
|
||||
Single<WithoutArgs<RustcNeverReturnsNullPointerParser>>,
|
||||
Single<WithoutArgs<RustcNoImplicitAutorefsParser>>,
|
||||
Single<WithoutArgs<RustcNounwindParser>>,
|
||||
Single<WithoutArgs<RustcOffloadKernelParser>>,
|
||||
Single<WithoutArgs<RustcPassIndirectlyInNonRusticAbisParser>>,
|
||||
Single<WithoutArgs<RustcReallocatorParser>>,
|
||||
Single<WithoutArgs<RustcShouldNotBeCalledOnConstItems>>,
|
||||
Single<WithoutArgs<SpecializationTraitParser>>,
|
||||
Single<WithoutArgs<StdInternalSymbolParser>>,
|
||||
|
|
@ -417,8 +431,7 @@ impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
|
|||
) {
|
||||
return;
|
||||
}
|
||||
let id = self.target_id;
|
||||
(self.emit_lint)(AttributeLint { lint_id: LintId::of(lint), id, span, kind });
|
||||
(self.emit_lint)(LintId::of(lint), span, kind);
|
||||
}
|
||||
|
||||
pub(crate) fn warn_unused_duplicate(&mut self, used_span: Span, unused_span: Span) {
|
||||
|
|
@ -663,11 +676,11 @@ pub struct SharedContext<'p, 'sess, S: Stage> {
|
|||
pub(crate) cx: &'p mut AttributeParser<'sess, S>,
|
||||
/// The span of the syntactical component this attribute was applied to
|
||||
pub(crate) target_span: Span,
|
||||
/// The id ([`NodeId`] if `S` is `Early`, [`HirId`] if `S` is `Late`) of the syntactical component this attribute was applied to
|
||||
pub(crate) target_id: S::Id,
|
||||
pub(crate) target: Option<rustc_hir::Target>,
|
||||
pub(crate) target: rustc_hir::Target,
|
||||
|
||||
pub(crate) emit_lint: &'p mut dyn FnMut(AttributeLint<S::Id>),
|
||||
/// The second argument of the closure is a [`NodeId`] if `S` is `Early` and a [`HirId`] if `S`
|
||||
/// is `Late` and is the ID of the syntactical component this attribute was applied to.
|
||||
pub(crate) emit_lint: &'p mut dyn FnMut(LintId, Span, AttributeLintKind),
|
||||
}
|
||||
|
||||
/// Context given to every attribute parser during finalization.
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@ use rustc_ast::{AttrItemKind, AttrStyle, NodeId, Safety};
|
|||
use rustc_errors::DiagCtxtHandle;
|
||||
use rustc_feature::{AttributeTemplate, Features};
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::lints::AttributeLint;
|
||||
use rustc_hir::lints::AttributeLintKind;
|
||||
use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, Target};
|
||||
use rustc_session::Session;
|
||||
use rustc_session::lint::BuiltinLintDiag;
|
||||
use rustc_session::lint::{BuiltinLintDiag, LintId};
|
||||
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
|
||||
|
||||
use crate::context::{AcceptContext, FinalizeContext, SharedContext, Stage};
|
||||
|
|
@ -113,16 +113,15 @@ impl<'sess> AttributeParser<'sess, Early> {
|
|||
p.parse_attribute_list(
|
||||
attrs,
|
||||
target_span,
|
||||
target_node_id,
|
||||
target,
|
||||
OmitDoc::Skip,
|
||||
std::convert::identity,
|
||||
|lint| {
|
||||
|lint_id, span, kind| {
|
||||
sess.psess.buffer_lint(
|
||||
lint.lint_id.lint,
|
||||
lint.span,
|
||||
lint.id,
|
||||
BuiltinLintDiag::AttributeLint(lint.kind),
|
||||
lint_id.lint,
|
||||
span,
|
||||
target_node_id,
|
||||
BuiltinLintDiag::AttributeLint(kind),
|
||||
)
|
||||
},
|
||||
)
|
||||
|
|
@ -135,6 +134,7 @@ impl<'sess> AttributeParser<'sess, Early> {
|
|||
attr: &ast::Attribute,
|
||||
target_span: Span,
|
||||
target_node_id: NodeId,
|
||||
target: Target,
|
||||
features: Option<&'sess Features>,
|
||||
emit_errors: ShouldEmit,
|
||||
parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser) -> Option<T>,
|
||||
|
|
@ -163,6 +163,7 @@ impl<'sess> AttributeParser<'sess, Early> {
|
|||
ParsedDescription::Attribute,
|
||||
target_span,
|
||||
target_node_id,
|
||||
target,
|
||||
features,
|
||||
emit_errors,
|
||||
&args,
|
||||
|
|
@ -183,6 +184,7 @@ impl<'sess> AttributeParser<'sess, Early> {
|
|||
parsed_description: ParsedDescription,
|
||||
target_span: Span,
|
||||
target_node_id: NodeId,
|
||||
target: Target,
|
||||
features: Option<&'sess Features>,
|
||||
emit_errors: ShouldEmit,
|
||||
args: &I,
|
||||
|
|
@ -196,29 +198,22 @@ impl<'sess> AttributeParser<'sess, Early> {
|
|||
sess,
|
||||
stage: Early { emit_errors },
|
||||
};
|
||||
let mut emit_lint = |lint: AttributeLint<NodeId>| {
|
||||
let mut emit_lint = |lint_id: LintId, span: Span, kind: AttributeLintKind| {
|
||||
sess.psess.buffer_lint(
|
||||
lint.lint_id.lint,
|
||||
lint.span,
|
||||
lint.id,
|
||||
BuiltinLintDiag::AttributeLint(lint.kind),
|
||||
lint_id.lint,
|
||||
span,
|
||||
target_node_id,
|
||||
BuiltinLintDiag::AttributeLint(kind),
|
||||
)
|
||||
};
|
||||
if let Some(safety) = attr_safety {
|
||||
parser.check_attribute_safety(
|
||||
&attr_path,
|
||||
inner_span,
|
||||
safety,
|
||||
&mut emit_lint,
|
||||
target_node_id,
|
||||
)
|
||||
parser.check_attribute_safety(&attr_path, inner_span, safety, &mut emit_lint)
|
||||
}
|
||||
let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext {
|
||||
shared: SharedContext {
|
||||
cx: &mut parser,
|
||||
target_span,
|
||||
target_id: target_node_id,
|
||||
target: None,
|
||||
target,
|
||||
emit_lint: &mut emit_lint,
|
||||
},
|
||||
attr_span,
|
||||
|
|
@ -266,11 +261,10 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
|
|||
&mut self,
|
||||
attrs: &[ast::Attribute],
|
||||
target_span: Span,
|
||||
target_id: S::Id,
|
||||
target: Target,
|
||||
omit_doc: OmitDoc,
|
||||
lower_span: impl Copy + Fn(Span) -> Span,
|
||||
mut emit_lint: impl FnMut(AttributeLint<S::Id>),
|
||||
mut emit_lint: impl FnMut(LintId, Span, AttributeLintKind),
|
||||
) -> Vec<Attribute> {
|
||||
let mut attributes = Vec::new();
|
||||
let mut attr_paths: Vec<RefPathParser<'_>> = Vec::new();
|
||||
|
|
@ -326,7 +320,6 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
|
|||
lower_span(n.item.span()),
|
||||
n.item.unsafety,
|
||||
&mut emit_lint,
|
||||
target_id,
|
||||
);
|
||||
|
||||
let parts =
|
||||
|
|
@ -378,8 +371,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
|
|||
shared: SharedContext {
|
||||
cx: self,
|
||||
target_span,
|
||||
target_id,
|
||||
target: Some(target),
|
||||
target,
|
||||
emit_lint: &mut emit_lint,
|
||||
},
|
||||
attr_span,
|
||||
|
|
@ -427,13 +419,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
|
|||
early_parsed_state.finalize_early_parsed_attributes(&mut attributes);
|
||||
for f in &S::parsers().finalizers {
|
||||
if let Some(attr) = f(&mut FinalizeContext {
|
||||
shared: SharedContext {
|
||||
cx: self,
|
||||
target_span,
|
||||
target_id,
|
||||
target: Some(target),
|
||||
emit_lint: &mut emit_lint,
|
||||
},
|
||||
shared: SharedContext { cx: self, target_span, target, emit_lint: &mut emit_lint },
|
||||
all_attrs: &attr_paths,
|
||||
}) {
|
||||
attributes.push(Attribute::Parsed(attr));
|
||||
|
|
|
|||
|
|
@ -113,8 +113,12 @@ impl ArgParser {
|
|||
Some(match value {
|
||||
AttrArgs::Empty => Self::NoArgs,
|
||||
AttrArgs::Delimited(args) => {
|
||||
// The arguments of rustc_dummy are not validated if the arguments are delimited
|
||||
if parts == &[sym::rustc_dummy] {
|
||||
// The arguments of rustc_dummy and diagnostic::do_not_recommend are not validated
|
||||
// if the arguments are delimited.
|
||||
// See https://doc.rust-lang.org/reference/attributes/diagnostics.html#r-attributes.diagnostic.namespace.unknown-invalid-syntax
|
||||
if parts == &[sym::rustc_dummy]
|
||||
|| parts == &[sym::diagnostic, sym::do_not_recommend]
|
||||
{
|
||||
return Some(ArgParser::List(MetaItemListParser {
|
||||
sub_parsers: ThinVec::new(),
|
||||
span: args.dspan.entire(),
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use rustc_ast::Safety;
|
||||
use rustc_feature::{AttributeSafety, BUILTIN_ATTRIBUTE_MAP};
|
||||
use rustc_hir::AttrPath;
|
||||
use rustc_hir::lints::{AttributeLint, AttributeLintKind};
|
||||
use rustc_hir::lints::AttributeLintKind;
|
||||
use rustc_session::lint::LintId;
|
||||
use rustc_session::lint::builtin::UNSAFE_ATTR_OUTSIDE_UNSAFE;
|
||||
use rustc_span::Span;
|
||||
|
|
@ -15,8 +15,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
|
|||
attr_path: &AttrPath,
|
||||
attr_span: Span,
|
||||
attr_safety: Safety,
|
||||
emit_lint: &mut impl FnMut(AttributeLint<S::Id>),
|
||||
target_id: S::Id,
|
||||
emit_lint: &mut impl FnMut(LintId, Span, AttributeLintKind),
|
||||
) {
|
||||
if matches!(self.stage.should_emit(), ShouldEmit::Nothing) {
|
||||
return;
|
||||
|
|
@ -82,16 +81,15 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
|
|||
},
|
||||
);
|
||||
} else {
|
||||
emit_lint(AttributeLint {
|
||||
lint_id: LintId::of(UNSAFE_ATTR_OUTSIDE_UNSAFE),
|
||||
id: target_id,
|
||||
span: path_span,
|
||||
kind: AttributeLintKind::UnsafeAttrOutsideUnsafe {
|
||||
emit_lint(
|
||||
LintId::of(UNSAFE_ATTR_OUTSIDE_UNSAFE),
|
||||
path_span,
|
||||
AttributeLintKind::UnsafeAttrOutsideUnsafe {
|
||||
attribute_name_span: path_span,
|
||||
sugg_spans: not_from_proc_macro
|
||||
.then(|| (diag_span.shrink_to_lo(), diag_span.shrink_to_hi())),
|
||||
},
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -253,19 +253,52 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
|
|||
}
|
||||
|
||||
let region = region.as_var();
|
||||
|
||||
let borrow = BorrowData {
|
||||
let borrow = |activation_location| BorrowData {
|
||||
kind,
|
||||
region,
|
||||
reserve_location: location,
|
||||
activation_location: TwoPhaseActivation::NotTwoPhase,
|
||||
activation_location,
|
||||
borrowed_place,
|
||||
assigned_place: *assigned_place,
|
||||
};
|
||||
let (idx, _) = self.location_map.insert_full(location, borrow);
|
||||
let idx = BorrowIndex::from(idx);
|
||||
|
||||
self.insert_as_pending_if_two_phase(location, assigned_place, kind, idx);
|
||||
let idx = if !kind.is_two_phase_borrow() {
|
||||
debug!(" -> {:?}", location);
|
||||
let (idx, _) = self
|
||||
.location_map
|
||||
.insert_full(location, borrow(TwoPhaseActivation::NotTwoPhase));
|
||||
BorrowIndex::from(idx)
|
||||
} else {
|
||||
// When we encounter a 2-phase borrow statement, it will always
|
||||
// be assigning into a temporary TEMP:
|
||||
//
|
||||
// TEMP = &foo
|
||||
//
|
||||
// so extract `temp`.
|
||||
let Some(temp) = assigned_place.as_local() else {
|
||||
span_bug!(
|
||||
self.body.source_info(location).span,
|
||||
"expected 2-phase borrow to assign to a local, not `{:?}`",
|
||||
assigned_place,
|
||||
);
|
||||
};
|
||||
|
||||
// Consider the borrow not activated to start. When we find an activation, we'll update
|
||||
// this field.
|
||||
let (idx, _) = self
|
||||
.location_map
|
||||
.insert_full(location, borrow(TwoPhaseActivation::NotActivated));
|
||||
let idx = BorrowIndex::from(idx);
|
||||
|
||||
// Insert `temp` into the list of pending activations. From
|
||||
// now on, we'll be on the lookout for a use of it. Note that
|
||||
// we are guaranteed that this use will come after the
|
||||
// assignment.
|
||||
let prev = self.pending_activations.insert(temp, idx);
|
||||
assert_eq!(prev, None, "temporary associated with multiple two phase borrows");
|
||||
|
||||
idx
|
||||
};
|
||||
|
||||
self.local_map.entry(borrowed_place.local).or_default().insert(idx);
|
||||
}
|
||||
|
|
@ -334,62 +367,3 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
|
|||
self.super_rvalue(rvalue, location)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> GatherBorrows<'a, 'tcx> {
|
||||
/// If this is a two-phase borrow, then we will record it
|
||||
/// as "pending" until we find the activating use.
|
||||
fn insert_as_pending_if_two_phase(
|
||||
&mut self,
|
||||
start_location: Location,
|
||||
assigned_place: &mir::Place<'tcx>,
|
||||
kind: mir::BorrowKind,
|
||||
borrow_index: BorrowIndex,
|
||||
) {
|
||||
debug!(
|
||||
"Borrows::insert_as_pending_if_two_phase({:?}, {:?}, {:?})",
|
||||
start_location, assigned_place, borrow_index,
|
||||
);
|
||||
|
||||
if !kind.allows_two_phase_borrow() {
|
||||
debug!(" -> {:?}", start_location);
|
||||
return;
|
||||
}
|
||||
|
||||
// When we encounter a 2-phase borrow statement, it will always
|
||||
// be assigning into a temporary TEMP:
|
||||
//
|
||||
// TEMP = &foo
|
||||
//
|
||||
// so extract `temp`.
|
||||
let Some(temp) = assigned_place.as_local() else {
|
||||
span_bug!(
|
||||
self.body.source_info(start_location).span,
|
||||
"expected 2-phase borrow to assign to a local, not `{:?}`",
|
||||
assigned_place,
|
||||
);
|
||||
};
|
||||
|
||||
// Consider the borrow not activated to start. When we find an activation, we'll update
|
||||
// this field.
|
||||
{
|
||||
let borrow_data = &mut self.location_map[borrow_index.as_usize()];
|
||||
borrow_data.activation_location = TwoPhaseActivation::NotActivated;
|
||||
}
|
||||
|
||||
// Insert `temp` into the list of pending activations. From
|
||||
// now on, we'll be on the lookout for a use of it. Note that
|
||||
// we are guaranteed that this use will come after the
|
||||
// assignment.
|
||||
let old_value = self.pending_activations.insert(temp, borrow_index);
|
||||
if let Some(old_index) = old_value {
|
||||
span_bug!(
|
||||
self.body.source_info(start_location).span,
|
||||
"found already pending activation for temp: {:?} \
|
||||
at borrow_index: {:?} with associated data {:?}",
|
||||
temp,
|
||||
old_index,
|
||||
self.location_map[old_index.as_usize()]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{Applicability, Diag, DiagCtxtHandle, struct_span_code_err};
|
||||
use rustc_hir as hir;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
// ignore-tidy-filelength
|
||||
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
|
||||
use std::iter;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
//! Print diagnostics to explain why values are borrowed.
|
||||
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
|
||||
use std::assert_matches::assert_matches;
|
||||
|
||||
use rustc_data_structures::assert_matches;
|
||||
use rustc_errors::{Applicability, Diag, EmissionGuarantee};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
|
|
|
|||
|
|
@ -162,8 +162,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
}
|
||||
for (_, (mut diag, count)) in std::mem::take(&mut self.diags_buffer.buffered_mut_errors) {
|
||||
if count > 10 {
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
diag.note(format!("...and {} other attempted mutable borrows", count - 10));
|
||||
}
|
||||
self.buffer_error(diag);
|
||||
|
|
@ -236,7 +234,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
/// LL | for (key, value) in dict {
|
||||
/// | ^^^^
|
||||
/// ```
|
||||
#[allow(rustc::diagnostic_outside_of_impl)] // FIXME
|
||||
pub(super) fn add_moved_or_invoked_closure_note(
|
||||
&self,
|
||||
location: Location,
|
||||
|
|
@ -820,7 +817,6 @@ impl UseSpans<'_> {
|
|||
}
|
||||
|
||||
/// Add a span label to the arguments of the closure, if it exists.
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
pub(super) fn args_subdiag(self, err: &mut Diag<'_>, f: impl FnOnce(Span) -> CaptureArgLabel) {
|
||||
if let UseSpans::ClosureUse { args_span, .. } = self {
|
||||
err.subdiagnostic(f(args_span));
|
||||
|
|
@ -829,7 +825,6 @@ impl UseSpans<'_> {
|
|||
|
||||
/// Add a span label to the use of the captured variable, if it exists.
|
||||
/// only adds label to the `path_span`
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
pub(super) fn var_path_only_subdiag(
|
||||
self,
|
||||
err: &mut Diag<'_>,
|
||||
|
|
@ -861,7 +856,6 @@ impl UseSpans<'_> {
|
|||
}
|
||||
|
||||
/// Add a subdiagnostic to the use of the captured variable, if it exists.
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
pub(super) fn var_subdiag(
|
||||
self,
|
||||
err: &mut Diag<'_>,
|
||||
|
|
@ -1225,8 +1219,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
self.borrow_spans(span, borrow.reserve_location)
|
||||
}
|
||||
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
fn explain_captures(
|
||||
&mut self,
|
||||
err: &mut Diag<'infcx>,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::{Applicability, Diag};
|
||||
use rustc_hir::intravisit::Visitor;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
|
||||
use core::ops::ControlFlow;
|
||||
|
||||
use either::Either;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use either::Either;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
//! Contains utilities for generating suggestions for borrowck errors related to unsatisfied
|
||||
//! outlives constraints.
|
||||
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
|
|
|
|||
|
|
@ -196,7 +196,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
// For generic associated types (GATs) which implied 'static requirement
|
||||
// from higher-ranked trait bounds (HRTB). Try to locate span of the trait
|
||||
// and the span which bounded to the trait for adding 'static lifetime suggestion
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
fn suggest_static_lifetime_for_gat_from_hrtb(
|
||||
&self,
|
||||
diag: &mut Diag<'_>,
|
||||
|
|
@ -421,9 +420,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
/// ```
|
||||
///
|
||||
/// Here we would be invoked with `fr = 'a` and `outlived_fr = 'b`.
|
||||
// FIXME: make this translatable
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
pub(crate) fn report_region_error(
|
||||
&mut self,
|
||||
fr: RegionVid,
|
||||
|
|
@ -577,7 +573,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
/// executing...
|
||||
/// = note: ...therefore, returned references to captured variables will escape the closure
|
||||
/// ```
|
||||
#[allow(rustc::diagnostic_outside_of_impl)] // FIXME
|
||||
fn report_fnmut_error(
|
||||
&self,
|
||||
errci: &ErrorConstraintInfo<'tcx>,
|
||||
|
|
@ -686,18 +681,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
borrowck_errors::borrowed_data_escapes_closure(self.infcx.tcx, *span, escapes_from);
|
||||
|
||||
if let Some((Some(outlived_fr_name), outlived_fr_span)) = outlived_fr_name_and_span {
|
||||
// FIXME: make this translatable
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
diag.span_label(
|
||||
outlived_fr_span,
|
||||
format!("`{outlived_fr_name}` declared here, outside of the {escapes_from} body",),
|
||||
);
|
||||
}
|
||||
|
||||
// FIXME: make this translatable
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
if let Some((Some(fr_name), fr_span)) = fr_name_and_span {
|
||||
diag.span_label(
|
||||
fr_span,
|
||||
|
|
@ -732,9 +721,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
let outlived_fr_region_name = self.give_region_a_name(errci.outlived_fr).unwrap();
|
||||
outlived_fr_region_name.highlight_region_name(&mut diag);
|
||||
|
||||
// FIXME: make this translatable
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
diag.span_label(
|
||||
*span,
|
||||
format!(
|
||||
|
|
@ -766,7 +752,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
/// | ^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it
|
||||
/// | is returning data with lifetime `'b`
|
||||
/// ```
|
||||
#[allow(rustc::diagnostic_outside_of_impl)] // FIXME
|
||||
fn report_general_error(&self, errci: &ErrorConstraintInfo<'tcx>) -> Diag<'infcx> {
|
||||
let ErrorConstraintInfo { fr, outlived_fr, span, category, .. } = errci;
|
||||
|
||||
|
|
@ -824,8 +809,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
/// LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> + 'a {
|
||||
/// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
/// ```
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
fn add_static_impl_trait_suggestion(
|
||||
&self,
|
||||
diag: &mut Diag<'_>,
|
||||
|
|
@ -966,7 +949,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
self.suggest_constrain_dyn_trait_in_impl(diag, &visitor.0, ident, self_ty);
|
||||
}
|
||||
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[instrument(skip(self, err), level = "debug")]
|
||||
fn suggest_constrain_dyn_trait_in_impl(
|
||||
&self,
|
||||
|
|
@ -1032,7 +1014,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
/// When encountering a lifetime error caused by the return type of a closure, check the
|
||||
/// corresponding trait bound and see if dereferencing the closure return value would satisfy
|
||||
/// them. If so, we produce a structured suggestion.
|
||||
|
|
@ -1160,7 +1141,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
fn suggest_move_on_borrowing_closure(&self, diag: &mut Diag<'_>) {
|
||||
let body = self.infcx.tcx.hir_body_owned_by(self.mir_def_id());
|
||||
let expr = &body.value.peel_blocks();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
|
||||
use std::fmt::{self, Display};
|
||||
use std::iter;
|
||||
|
||||
|
|
|
|||
|
|
@ -1301,7 +1301,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
|
|||
(Read(kind), BorrowKind::Mut { .. }) => {
|
||||
// Reading from mere reservations of mutable-borrows is OK.
|
||||
if !is_active(this.dominators(), borrow, location) {
|
||||
assert!(borrow.kind.allows_two_phase_borrow());
|
||||
assert!(borrow.kind.is_two_phase_borrow());
|
||||
return ControlFlow::Continue(());
|
||||
}
|
||||
|
||||
|
|
@ -1464,7 +1464,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
|
|||
}
|
||||
BorrowKind::Mut { .. } => {
|
||||
let wk = WriteKind::MutableBorrow(bk);
|
||||
if bk.allows_two_phase_borrow() {
|
||||
if bk.is_two_phase_borrow() {
|
||||
(Deep, Reservation(wk))
|
||||
} else {
|
||||
(Deep, Write(wk))
|
||||
|
|
|
|||
|
|
@ -287,8 +287,6 @@ pub(crate) fn emit_nll_mir<'tcx>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
pub(super) fn dump_annotation<'tcx, 'infcx>(
|
||||
infcx: &'infcx BorrowckInferCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
|
|
|
|||
|
|
@ -264,7 +264,7 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> {
|
|||
}
|
||||
BorrowKind::Mut { .. } => {
|
||||
let wk = WriteKind::MutableBorrow(bk);
|
||||
if bk.allows_two_phase_borrow() {
|
||||
if bk.is_two_phase_borrow() {
|
||||
(Deep, Reservation(wk))
|
||||
} else {
|
||||
(Deep, Write(wk))
|
||||
|
|
@ -384,7 +384,7 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> {
|
|||
// Reading from mere reservations of mutable-borrows is OK.
|
||||
if !is_active(this.dominators, borrow, location) {
|
||||
// If the borrow isn't active yet, reads don't invalidate it
|
||||
assert!(borrow.kind.allows_two_phase_borrow());
|
||||
assert!(borrow.kind.is_two_phase_borrow());
|
||||
return ControlFlow::Continue(());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -229,8 +229,9 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
|||
// not ready to process them yet.
|
||||
// - Then compute the implied bounds. This will adjust
|
||||
// the `region_bound_pairs` and so forth.
|
||||
// - After this is done, we'll process the constraints, once
|
||||
// the `relations` is built.
|
||||
// - After this is done, we'll register the constraints in
|
||||
// the `BorrowckInferCtxt`. Checking these constraints is
|
||||
// handled later by actual borrow checking.
|
||||
let mut normalized_inputs_and_output =
|
||||
Vec::with_capacity(self.universal_regions.unnormalized_input_tys.len() + 1);
|
||||
for ty in unnormalized_input_output_tys {
|
||||
|
|
@ -254,6 +255,15 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
|||
constraints.push(c)
|
||||
}
|
||||
|
||||
// Currently `implied_outlives_bounds` will normalize the provided
|
||||
// `Ty`, despite this it's still important to normalize the ty ourselves
|
||||
// as normalization may introduce new region variables (#136547).
|
||||
//
|
||||
// If we do not add implied bounds for the type involving these new
|
||||
// region variables then we'll wind up with the normalized form of
|
||||
// the signature having not-wf types due to unsatisfied region
|
||||
// constraints.
|
||||
//
|
||||
// Note: we need this in examples like
|
||||
// ```
|
||||
// trait Foo {
|
||||
|
|
@ -262,7 +272,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
|||
// }
|
||||
// impl Foo for () {
|
||||
// type Bar = ();
|
||||
// fn foo(&self) ->&() {}
|
||||
// fn foo(&self) -> &() {}
|
||||
// }
|
||||
// ```
|
||||
// Both &Self::Bar and &() are WF
|
||||
|
|
@ -277,6 +287,15 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
|||
}
|
||||
|
||||
// Add implied bounds from impl header.
|
||||
//
|
||||
// We don't use `assumed_wf_types` to source the entire set of implied bounds for
|
||||
// a few reasons:
|
||||
// - `DefiningTy` for closure has the `&'env Self` type while `assumed_wf_types` doesn't
|
||||
// - We compute implied bounds from the unnormalized types in the `DefiningTy` but do not
|
||||
// do so for types in impl headers
|
||||
// - We must compute the normalized signature and then compute implied bounds from that
|
||||
// in order to connect any unconstrained region vars created during normalization to
|
||||
// the types of the locals corresponding to the inputs and outputs of the item. (#136547)
|
||||
if matches!(tcx.def_kind(defining_ty_def_id), DefKind::AssocFn | DefKind::AssocConst) {
|
||||
for &(ty, _) in tcx.assumed_wf_types(tcx.local_parent(defining_ty_def_id)) {
|
||||
let result: Result<_, ErrorGuaranteed> = param_env
|
||||
|
|
@ -352,10 +371,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
|||
known_type_outlives_obligations.push(outlives);
|
||||
}
|
||||
|
||||
/// Update the type of a single local, which should represent
|
||||
/// either the return type of the MIR or one of its arguments. At
|
||||
/// the same time, compute and add any implied bounds that come
|
||||
/// from this local.
|
||||
/// Compute and add any implied bounds that come from a given type.
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn add_implied_bounds(
|
||||
&mut self,
|
||||
|
|
|
|||
|
|
@ -7,9 +7,8 @@
|
|||
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
|
||||
//! contain revealed `impl Trait` values).
|
||||
|
||||
use std::assert_matches::assert_matches;
|
||||
|
||||
use itertools::Itertools;
|
||||
use rustc_data_structures::assert_matches;
|
||||
use rustc_hir as hir;
|
||||
use rustc_infer::infer::{BoundRegionConversionTime, RegionVariableOrigin};
|
||||
use rustc_middle::mir::*;
|
||||
|
|
|
|||
|
|
@ -11,9 +11,6 @@
|
|||
//! The code in this file doesn't *do anything* with those results; it
|
||||
//! just returns them for other code to use.
|
||||
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::iter;
|
||||
|
||||
|
|
@ -207,10 +204,10 @@ struct UniversalRegionIndices<'tcx> {
|
|||
/// `ty::Region` to the internal `RegionVid` we are using. This is
|
||||
/// used because trait matching and type-checking will feed us
|
||||
/// region constraints that reference those regions and we need to
|
||||
/// be able to map them to our internal `RegionVid`. This is
|
||||
/// basically equivalent to an `GenericArgs`, except that it also
|
||||
/// contains an entry for `ReStatic` -- it might be nice to just
|
||||
/// use an args, and then handle `ReStatic` another way.
|
||||
/// be able to map them to our internal `RegionVid`.
|
||||
///
|
||||
/// This is similar to just using `GenericArgs`, except that it contains
|
||||
/// an entry for `'static`, and also late bound parameters in scope.
|
||||
indices: FxIndexMap<ty::Region<'tcx>, RegionVid>,
|
||||
|
||||
/// The vid assigned to `'static`. Used only for diagnostics.
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ use rustc_attr_parsing::{
|
|||
AttributeParser, CFG_TEMPLATE, ParsedDescription, ShouldEmit, parse_cfg_entry,
|
||||
};
|
||||
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
|
||||
use rustc_hir::AttrPath;
|
||||
use rustc_hir::attrs::CfgEntry;
|
||||
use rustc_hir::{AttrPath, Target};
|
||||
use rustc_parse::exp;
|
||||
use rustc_span::{ErrorGuaranteed, Span, sym};
|
||||
|
||||
|
|
@ -52,6 +52,8 @@ fn parse_cfg(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream) -> Result<CfgEntry,
|
|||
ParsedDescription::Macro,
|
||||
span,
|
||||
cx.current_expansion.lint_node_id,
|
||||
// Doesn't matter what the target actually is here.
|
||||
Target::Crate,
|
||||
Some(cx.ecfg.features),
|
||||
ShouldEmit::ErrorsAndLints,
|
||||
&meta,
|
||||
|
|
|
|||
|
|
@ -19,9 +19,8 @@ pub(crate) fn expand_compile_error<'cx>(
|
|||
Err(guar) => return ExpandResult::Ready(DummyResult::any(sp, guar)),
|
||||
};
|
||||
|
||||
#[expect(rustc::diagnostic_outside_of_impl, reason = "diagnostic message is specified by user")]
|
||||
#[expect(rustc::untranslatable_diagnostic, reason = "diagnostic message is specified by user")]
|
||||
let guar = cx.dcx().span_err(sp, var.to_string());
|
||||
cx.resolver.mark_scope_with_compile_error(cx.current_expansion.lint_node_id);
|
||||
|
||||
ExpandResult::Ready(DummyResult::any(sp, guar))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -503,10 +503,6 @@ pub(crate) struct EnvNotDefinedWithUserMessage {
|
|||
impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for EnvNotDefinedWithUserMessage {
|
||||
#[track_caller]
|
||||
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
|
||||
#[expect(
|
||||
rustc::untranslatable_diagnostic,
|
||||
reason = "cannot translate user-provided messages"
|
||||
)]
|
||||
let mut diag = Diag::new(dcx, level, self.msg_from_user.to_string());
|
||||
diag.span(self.span);
|
||||
diag
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(decl_macro)]
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
//! The expansion from a test function to the appropriate test struct for libtest
|
||||
//! Ideally, this code would be in libtest but for efficiency and error messages it lives here.
|
||||
|
||||
use std::assert_matches::assert_matches;
|
||||
use std::iter;
|
||||
|
||||
use rustc_ast::{self as ast, GenericParamKind, HasNodeId, attr, join_path_idents};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_attr_parsing::AttributeParser;
|
||||
use rustc_data_structures::assert_matches;
|
||||
use rustc_errors::{Applicability, Diag, Level};
|
||||
use rustc_expand::base::*;
|
||||
use rustc_hir::Attribute;
|
||||
|
|
|
|||
|
|
@ -78,8 +78,6 @@ type UnexpectedExprKind<'a> = Result<(Diag<'a>, bool /* has_suggestions */), Err
|
|||
/// The returned bool indicates whether an applicable suggestion has already been
|
||||
/// added to the diagnostic to avoid emitting multiple suggestions. `Err(Err(ErrorGuaranteed))`
|
||||
/// indicates that an ast error was encountered.
|
||||
// FIXME(Nilstrieb) Make this function setup translatable
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
pub(crate) fn expr_to_spanned_string<'a>(
|
||||
cx: &'a mut ExtCtxt<'_>,
|
||||
expr: Box<ast::Expr>,
|
||||
|
|
|
|||
|
|
@ -14,11 +14,10 @@ diff --git a/coretests/tests/lib.rs b/coretests/tests/lib.rs
|
|||
index 1e336bf..35e6f54 100644
|
||||
--- a/coretests/tests/lib.rs
|
||||
+++ b/coretests/tests/lib.rs
|
||||
@@ -2,5 +2,4 @@
|
||||
@@ -2,4 +2,3 @@
|
||||
// tidy-alphabetical-start
|
||||
-#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
|
||||
#![cfg_attr(test, feature(cfg_select))]
|
||||
#![feature(alloc_layout_extra)]
|
||||
#![feature(array_ptr_get)]
|
||||
diff --git a/coretests/tests/atomic.rs b/coretests/tests/atomic.rs
|
||||
index b735957..ea728b6 100644
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
// tidy-alphabetical-start
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
// Note: please avoid adding other feature gates where possible
|
||||
#![feature(rustc_private)]
|
||||
// Only used to define intrinsics in `compiler_builtins.rs`.
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
use std::assert_matches::assert_matches;
|
||||
|
||||
use rustc_abi::{BackendRepr, Float, Integer, Primitive, Scalar};
|
||||
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
||||
use rustc_codegen_ssa::mir::operand::OperandValue;
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
use rustc_data_structures::assert_matches;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_middle::ty::Instance;
|
||||
use rustc_middle::ty::layout::TyAndLayout;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
//! Set and unset common attributes on LLVM values.
|
||||
use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, OptimizeAttr, RtsanSetting};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::find_attr;
|
||||
use rustc_middle::middle::codegen_fn_attrs::{
|
||||
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, SanitizerFnAttrs,
|
||||
};
|
||||
|
|
@ -470,9 +471,7 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
|
|||
{
|
||||
to_add.push(create_alloc_family_attr(cx.llcx));
|
||||
if let Some(instance) = instance
|
||||
&& let Some(zv) =
|
||||
tcx.get_attr(instance.def_id(), rustc_span::sym::rustc_allocator_zeroed_variant)
|
||||
&& let Some(name) = zv.value_str()
|
||||
&& let Some(name) = find_attr!(tcx.get_all_attrs(instance.def_id()), rustc_hir::attrs::AttributeKind::RustcAllocatorZeroedVariant {name} => name)
|
||||
{
|
||||
to_add.push(llvm::CreateAttrStringValue(
|
||||
cx.llcx,
|
||||
|
|
@ -517,16 +516,7 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
|
|||
to_add.push(llvm::CreateAllocKindAttr(cx.llcx, AllocKindFlags::Free));
|
||||
// applies to argument place instead of function place
|
||||
let allocated_pointer = AttributeKind::AllocatedPointer.create_attr(cx.llcx);
|
||||
let attrs: &[_] = if llvm_util::get_version() >= (21, 0, 0) {
|
||||
// "Does not capture provenance" means "if the function call stashes the pointer somewhere,
|
||||
// accessing that pointer after the function returns is UB". That is definitely the case here since
|
||||
// freeing will destroy the provenance.
|
||||
let captures_addr = AttributeKind::CapturesAddress.create_attr(cx.llcx);
|
||||
&[allocated_pointer, captures_addr]
|
||||
} else {
|
||||
&[allocated_pointer]
|
||||
};
|
||||
attributes::apply_to_llfn(llfn, AttributePlace::Argument(0), attrs);
|
||||
attributes::apply_to_llfn(llfn, AttributePlace::Argument(0), &[allocated_pointer]);
|
||||
}
|
||||
if let Some(align) = codegen_fn_attrs.alignment {
|
||||
llvm::set_alignment(llfn, align);
|
||||
|
|
|
|||
|
|
@ -55,6 +55,10 @@ impl<'ll> OffloadGlobals<'ll> {
|
|||
let init_ty = cx.type_func(&[], cx.type_void());
|
||||
let init_rtls = declare_offload_fn(cx, "__tgt_init_all_rtls", init_ty);
|
||||
|
||||
// We want LLVM's openmp-opt pass to pick up and optimize this module, since it covers both
|
||||
// openmp and offload optimizations.
|
||||
llvm::add_module_flag_u32(cx.llmod(), llvm::ModuleFlagMergeBehavior::Max, "openmp", 51);
|
||||
|
||||
OffloadGlobals {
|
||||
launcher_fn,
|
||||
launcher_ty,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
use std::assert_matches::assert_matches;
|
||||
use std::sync::Arc;
|
||||
|
||||
use itertools::Itertools;
|
||||
use rustc_abi::Align;
|
||||
use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, ConstCodegenMethods};
|
||||
use rustc_data_structures::assert_matches;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use std::assert_matches::assert_matches;
|
||||
use std::cmp::Ordering;
|
||||
use std::ffi::c_uint;
|
||||
use std::ptr;
|
||||
|
|
@ -13,6 +12,7 @@ use rustc_codegen_ssa::errors::{ExpectedPointerMutability, InvalidMonomorphizati
|
|||
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
|
||||
use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue};
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
use rustc_data_structures::assert_matches;
|
||||
use rustc_hir::def_id::LOCAL_CRATE;
|
||||
use rustc_hir::{self as hir};
|
||||
use rustc_middle::mir::BinOp;
|
||||
|
|
@ -560,6 +560,12 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
sym::amdgpu_dispatch_ptr => {
|
||||
let val = self.call_intrinsic("llvm.amdgcn.dispatch.ptr", &[], &[]);
|
||||
// Relying on `LLVMBuildPointerCast` to produce an addrspacecast
|
||||
self.pointercast(val, self.type_ptr())
|
||||
}
|
||||
|
||||
_ if name.as_str().starts_with("simd_") => {
|
||||
// Unpack non-power-of-2 #[repr(packed, simd)] arguments.
|
||||
// This gives them the expected layout of a regular #[repr(simd)] vector.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use std::assert_matches::assert_matches;
|
||||
use std::marker::PhantomData;
|
||||
use std::panic::AssertUnwindSafe;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
|
@ -8,6 +7,7 @@ use std::{fs, io, mem, str, thread};
|
|||
|
||||
use rustc_abi::Size;
|
||||
use rustc_ast::attr;
|
||||
use rustc_data_structures::assert_matches;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::jobserver::{self, Acquired};
|
||||
use rustc_data_structures::memmap::Mmap;
|
||||
|
|
|
|||
|
|
@ -335,6 +335,24 @@ fn process_builtin_attrs(
|
|||
AttributeKind::InstructionSet(instruction_set) => {
|
||||
codegen_fn_attrs.instruction_set = Some(*instruction_set)
|
||||
}
|
||||
AttributeKind::RustcAllocator => {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR
|
||||
}
|
||||
AttributeKind::RustcDeallocator => {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::DEALLOCATOR
|
||||
}
|
||||
AttributeKind::RustcReallocator => {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::REALLOCATOR
|
||||
}
|
||||
AttributeKind::RustcAllocatorZeroed => {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED
|
||||
}
|
||||
AttributeKind::RustcNounwind => {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND
|
||||
}
|
||||
AttributeKind::RustcOffloadKernel => {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::OFFLOAD_KERNEL
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
@ -344,20 +362,10 @@ fn process_builtin_attrs(
|
|||
};
|
||||
|
||||
match name {
|
||||
sym::rustc_allocator => codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR,
|
||||
sym::rustc_nounwind => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND,
|
||||
sym::rustc_reallocator => codegen_fn_attrs.flags |= CodegenFnAttrFlags::REALLOCATOR,
|
||||
sym::rustc_deallocator => codegen_fn_attrs.flags |= CodegenFnAttrFlags::DEALLOCATOR,
|
||||
sym::rustc_allocator_zeroed => {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED
|
||||
}
|
||||
sym::patchable_function_entry => {
|
||||
codegen_fn_attrs.patchable_function_entry =
|
||||
parse_patchable_function_entry(tcx, attr);
|
||||
}
|
||||
sym::rustc_offload_kernel => {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::OFFLOAD_KERNEL
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
// tidy-alphabetical-start
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(file_buffered)]
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
| sym::unreachable
|
||||
| sym::cold_path
|
||||
| sym::breakpoint
|
||||
| sym::amdgpu_dispatch_ptr
|
||||
| sym::assert_zero_valid
|
||||
| sym::assert_mem_uninitialized_valid
|
||||
| sym::assert_inhabited
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::assert_matches::assert_matches;
|
||||
use std::ops::Deref;
|
||||
|
||||
use rustc_abi::{Align, Scalar, Size, WrappingRange};
|
||||
use rustc_data_structures::assert_matches;
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
|
||||
|
|
|
|||
|
|
@ -140,9 +140,9 @@ const_eval_incompatible_return_types =
|
|||
const_eval_interior_mutable_borrow_escaping =
|
||||
interior mutable shared borrows of temporaries that have their lifetime extended until the end of the program are not allowed
|
||||
.label = this borrow of an interior mutable value refers to such a temporary
|
||||
.note = Temporaries in constants and statics can have their lifetime extended until the end of the program
|
||||
.note2 = To avoid accidentally creating global mutable state, such temporaries must be immutable
|
||||
.help = If you really want global mutable state, try replacing the temporary by an interior mutable `static` or a `static mut`
|
||||
.note = temporaries in constants and statics can have their lifetime extended until the end of the program
|
||||
.note2 = to avoid accidentally creating global mutable state, such temporaries must be immutable
|
||||
.help = if you really want global mutable state, try replacing the temporary by an interior mutable `static` or a `static mut`
|
||||
|
||||
const_eval_intern_kind = {$kind ->
|
||||
[static] static
|
||||
|
|
@ -225,9 +225,9 @@ const_eval_modified_global =
|
|||
const_eval_mutable_borrow_escaping =
|
||||
mutable borrows of temporaries that have their lifetime extended until the end of the program are not allowed
|
||||
.label = this mutable borrow refers to such a temporary
|
||||
.note = Temporaries in constants and statics can have their lifetime extended until the end of the program
|
||||
.note2 = To avoid accidentally creating global mutable state, such temporaries must be immutable
|
||||
.help = If you really want global mutable state, try replacing the temporary by an interior mutable `static` or a `static mut`
|
||||
.note = temporaries in constants and statics can have their lifetime extended until the end of the program
|
||||
.note2 = to avoid accidentally creating global mutable state, such temporaries must be immutable
|
||||
.help = if you really want global mutable state, try replacing the temporary by an interior mutable `static` or a `static mut`
|
||||
|
||||
const_eval_mutable_ptr_in_final = encountered mutable pointer in final value of {const_eval_intern_kind}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
//! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations.
|
||||
|
||||
use std::assert_matches::assert_matches;
|
||||
use std::borrow::Cow;
|
||||
use std::mem;
|
||||
use std::num::NonZero;
|
||||
use std::ops::Deref;
|
||||
|
||||
use rustc_data_structures::assert_matches;
|
||||
use rustc_errors::{Diag, ErrorGuaranteed};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::DefId;
|
||||
|
|
|
|||
|
|
@ -125,9 +125,6 @@ pub(crate) struct FnCallNonConst<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
|
||||
// FIXME: make this translatable
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> {
|
||||
let tcx = ccx.tcx;
|
||||
let caller = ccx.def_id();
|
||||
|
|
|
|||
|
|
@ -394,8 +394,10 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
|
|||
typing_env: ty::TypingEnv<'tcx>,
|
||||
) -> Result<R, ErrorHandled> {
|
||||
let def = cid.instance.def.def_id();
|
||||
let is_static = tcx.is_static(def);
|
||||
// #[type_const] don't have bodys
|
||||
debug_assert!(!tcx.is_type_const(def), "CTFE tried to evaluate type-const: {:?}", def);
|
||||
|
||||
let is_static = tcx.is_static(def);
|
||||
let mut ecx = InterpCx::new(
|
||||
tcx,
|
||||
tcx.def_span(def),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use rustc_abi::FieldIdx;
|
||||
use rustc_ast::Mutability;
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_middle::mir::interpret::CtfeProvenance;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::layout::TyAndLayout;
|
||||
use rustc_middle::ty::{self, Const, ScalarInt, Ty};
|
||||
|
|
@ -8,7 +8,8 @@ use rustc_span::{Symbol, sym};
|
|||
|
||||
use crate::const_eval::CompileTimeMachine;
|
||||
use crate::interpret::{
|
||||
Immediate, InterpCx, InterpResult, MPlaceTy, MemoryKind, Writeable, interp_ok,
|
||||
CtfeProvenance, Immediate, InterpCx, InterpResult, MPlaceTy, MemoryKind, Scalar, Writeable,
|
||||
interp_ok,
|
||||
};
|
||||
|
||||
impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
||||
|
|
@ -35,6 +36,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
|||
|
||||
interp_ok((variant_id, self.project_downcast(&field_dest, variant_id)?))
|
||||
};
|
||||
let ptr_bit_width = || self.tcx.data_layout.pointer_size().bits();
|
||||
match field.name {
|
||||
sym::kind => {
|
||||
let variant_index = match ty.kind() {
|
||||
|
|
@ -64,17 +66,65 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
|||
|
||||
variant
|
||||
}
|
||||
// For now just merge all primitives into one `Leaf` variant with no data
|
||||
ty::Uint(_) | ty::Int(_) | ty::Float(_) | ty::Char | ty::Bool => {
|
||||
downcast(sym::Leaf)?.0
|
||||
ty::Bool => {
|
||||
let (variant, _variant_place) = downcast(sym::Bool)?;
|
||||
variant
|
||||
}
|
||||
ty::Char => {
|
||||
let (variant, _variant_place) = downcast(sym::Char)?;
|
||||
variant
|
||||
}
|
||||
ty::Int(int_ty) => {
|
||||
let (variant, variant_place) = downcast(sym::Int)?;
|
||||
let place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||
self.write_int_type_info(
|
||||
place,
|
||||
int_ty.bit_width().unwrap_or_else(/* isize */ ptr_bit_width),
|
||||
true,
|
||||
)?;
|
||||
variant
|
||||
}
|
||||
ty::Uint(uint_ty) => {
|
||||
let (variant, variant_place) = downcast(sym::Int)?;
|
||||
let place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||
self.write_int_type_info(
|
||||
place,
|
||||
uint_ty.bit_width().unwrap_or_else(/* usize */ ptr_bit_width),
|
||||
false,
|
||||
)?;
|
||||
variant
|
||||
}
|
||||
ty::Float(float_ty) => {
|
||||
let (variant, variant_place) = downcast(sym::Float)?;
|
||||
let place = self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||
self.write_float_type_info(place, float_ty.bit_width())?;
|
||||
variant
|
||||
}
|
||||
ty::Str => {
|
||||
let (variant, _variant_place) = downcast(sym::Str)?;
|
||||
variant
|
||||
}
|
||||
ty::Ref(_, ty, mutability) => {
|
||||
let (variant, variant_place) = downcast(sym::Reference)?;
|
||||
let reference_place =
|
||||
self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||
self.write_reference_type_info(reference_place, *ty, *mutability)?;
|
||||
|
||||
variant
|
||||
}
|
||||
ty::RawPtr(ty, mutability) => {
|
||||
let (variant, variant_place) = downcast(sym::Pointer)?;
|
||||
let pointer_place =
|
||||
self.project_field(&variant_place, FieldIdx::ZERO)?;
|
||||
|
||||
self.write_pointer_type_info(pointer_place, *ty, *mutability)?;
|
||||
|
||||
variant
|
||||
}
|
||||
ty::Adt(_, _)
|
||||
| ty::Foreign(_)
|
||||
| ty::Str
|
||||
| ty::Pat(_, _)
|
||||
| ty::Slice(_)
|
||||
| ty::RawPtr(..)
|
||||
| ty::Ref(..)
|
||||
| ty::FnDef(..)
|
||||
| ty::FnPtr(..)
|
||||
| ty::UnsafeBinder(..)
|
||||
|
|
@ -203,4 +253,97 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> {
|
|||
|
||||
interp_ok(())
|
||||
}
|
||||
|
||||
fn write_int_type_info(
|
||||
&mut self,
|
||||
place: impl Writeable<'tcx, CtfeProvenance>,
|
||||
bit_width: u64,
|
||||
signed: bool,
|
||||
) -> InterpResult<'tcx> {
|
||||
for (field_idx, field) in
|
||||
place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated()
|
||||
{
|
||||
let field_place = self.project_field(&place, field_idx)?;
|
||||
match field.name {
|
||||
sym::bits => self.write_scalar(
|
||||
Scalar::from_u32(bit_width.try_into().expect("bit_width overflowed")),
|
||||
&field_place,
|
||||
)?,
|
||||
sym::signed => self.write_scalar(Scalar::from_bool(signed), &field_place)?,
|
||||
other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"),
|
||||
}
|
||||
}
|
||||
interp_ok(())
|
||||
}
|
||||
|
||||
fn write_float_type_info(
|
||||
&mut self,
|
||||
place: impl Writeable<'tcx, CtfeProvenance>,
|
||||
bit_width: u64,
|
||||
) -> InterpResult<'tcx> {
|
||||
for (field_idx, field) in
|
||||
place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated()
|
||||
{
|
||||
let field_place = self.project_field(&place, field_idx)?;
|
||||
match field.name {
|
||||
sym::bits => self.write_scalar(
|
||||
Scalar::from_u32(bit_width.try_into().expect("bit_width overflowed")),
|
||||
&field_place,
|
||||
)?,
|
||||
other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"),
|
||||
}
|
||||
}
|
||||
interp_ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn write_reference_type_info(
|
||||
&mut self,
|
||||
place: impl Writeable<'tcx, CtfeProvenance>,
|
||||
ty: Ty<'tcx>,
|
||||
mutability: Mutability,
|
||||
) -> InterpResult<'tcx> {
|
||||
// Iterate over all fields of `type_info::Reference`.
|
||||
for (field_idx, field) in
|
||||
place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated()
|
||||
{
|
||||
let field_place = self.project_field(&place, field_idx)?;
|
||||
|
||||
match field.name {
|
||||
// Write the `TypeId` of the reference's inner type to the `ty` field.
|
||||
sym::pointee => self.write_type_id(ty, &field_place)?,
|
||||
// Write the boolean representing the reference's mutability to the `mutable` field.
|
||||
sym::mutable => {
|
||||
self.write_scalar(Scalar::from_bool(mutability.is_mut()), &field_place)?
|
||||
}
|
||||
other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"),
|
||||
}
|
||||
}
|
||||
interp_ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn write_pointer_type_info(
|
||||
&mut self,
|
||||
place: impl Writeable<'tcx, CtfeProvenance>,
|
||||
ty: Ty<'tcx>,
|
||||
mutability: Mutability,
|
||||
) -> InterpResult<'tcx> {
|
||||
// Iterate over all fields of `type_info::Pointer`.
|
||||
for (field_idx, field) in
|
||||
place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated()
|
||||
{
|
||||
let field_place = self.project_field(&place, field_idx)?;
|
||||
|
||||
match field.name {
|
||||
// Write the `TypeId` of the pointer's inner type to the `ty` field.
|
||||
sym::pointee => self.write_type_id(ty, &field_place)?,
|
||||
// Write the boolean representing the pointer's mutability to the `mutable` field.
|
||||
sym::mutable => {
|
||||
self.write_scalar(Scalar::from_bool(mutability.is_mut()), &field_place)?
|
||||
}
|
||||
other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"),
|
||||
}
|
||||
}
|
||||
|
||||
interp_ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
//! Manages calling a concrete function (with known MIR body) with argument passing,
|
||||
//! and returning the return value to the caller.
|
||||
use std::assert_matches::assert_matches;
|
||||
use std::borrow::Cow;
|
||||
|
||||
use either::{Left, Right};
|
||||
use rustc_abi::{self as abi, ExternAbi, FieldIdx, Integer, VariantIdx};
|
||||
use rustc_data_structures::assert_matches;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::ty::layout::{IntegerExt, TyAndLayout};
|
||||
use rustc_middle::ty::{self, AdtDef, Instance, Ty, VariantDef};
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
use std::assert_matches::assert_matches;
|
||||
|
||||
use rustc_abi::{FieldIdx, Integer};
|
||||
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
|
||||
use rustc_apfloat::{Float, FloatConvert};
|
||||
use rustc_data_structures::assert_matches;
|
||||
use rustc_middle::mir::CastKind;
|
||||
use rustc_middle::mir::interpret::{InterpResult, PointerArithmetic, Scalar};
|
||||
use rustc_middle::ty::adjustment::PointerCoercion;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use std::assert_matches::debug_assert_matches;
|
||||
|
||||
use either::{Left, Right};
|
||||
use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout};
|
||||
use rustc_data_structures::debug_assert_matches;
|
||||
use rustc_errors::DiagCtxtHandle;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::limit::Limit;
|
||||
|
|
@ -233,7 +232,6 @@ pub fn format_interp_error<'tcx>(dcx: DiagCtxtHandle<'_>, e: InterpErrorInfo<'tc
|
|||
backtrace.print_backtrace();
|
||||
// FIXME(fee1-dead), HACK: we want to use the error as title therefore we can just extract the
|
||||
// label and arguments from the InterpError.
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
let mut diag = dcx.struct_allow("");
|
||||
let msg = e.diagnostic_message();
|
||||
e.add_args(&mut diag);
|
||||
|
|
|
|||
|
|
@ -4,10 +4,9 @@
|
|||
|
||||
mod simd;
|
||||
|
||||
use std::assert_matches::assert_matches;
|
||||
|
||||
use rustc_abi::{FIRST_VARIANT, FieldIdx, HasDataLayout, Size, VariantIdx};
|
||||
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
|
||||
use rustc_data_structures::assert_matches;
|
||||
use rustc_hir::def_id::CRATE_DEF_ID;
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, read_target_uint, write_target_uint};
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use either::Either;
|
|||
use rustc_abi::{BackendRepr, Endian};
|
||||
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
|
||||
use rustc_apfloat::{Float, Round};
|
||||
use rustc_data_structures::assert_matches;
|
||||
use rustc_middle::mir::interpret::{InterpErrorKind, Pointer, UndefinedBehaviorInfo};
|
||||
use rustc_middle::ty::{FloatTy, ScalarInt, SimdAlign};
|
||||
use rustc_middle::{bug, err_ub_format, mir, span_bug, throw_unsup_format, ty};
|
||||
|
|
@ -10,7 +11,7 @@ use tracing::trace;
|
|||
|
||||
use super::{
|
||||
ImmTy, InterpCx, InterpResult, Machine, MinMax, MulAddType, OpTy, PlaceTy, Provenance, Scalar,
|
||||
Size, TyAndLayout, assert_matches, interp_ok, throw_ub_format,
|
||||
Size, TyAndLayout, interp_ok, throw_ub_format,
|
||||
};
|
||||
use crate::interpret::Writeable;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
//! integer. It is crucial that these operations call `check_align` *before*
|
||||
//! short-circuiting the empty case!
|
||||
|
||||
use std::assert_matches::assert_matches;
|
||||
use std::borrow::{Borrow, Cow};
|
||||
use std::cell::Cell;
|
||||
use std::collections::VecDeque;
|
||||
|
|
@ -14,6 +13,7 @@ use std::{fmt, ptr};
|
|||
|
||||
use rustc_abi::{Align, HasDataLayout, Size};
|
||||
use rustc_ast::Mutability;
|
||||
use rustc_data_structures::assert_matches;
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
||||
use rustc_middle::mir::display_allocation;
|
||||
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
//! Functions concerning immediate values and operands, and reading from operands.
|
||||
//! All high-level functions to read from memory work on operands as sources.
|
||||
|
||||
use std::assert_matches::assert_matches;
|
||||
|
||||
use either::{Either, Left, Right};
|
||||
use rustc_abi as abi;
|
||||
use rustc_abi::{BackendRepr, HasDataLayout, Size};
|
||||
use rustc_data_structures::assert_matches;
|
||||
use rustc_hir::def::Namespace;
|
||||
use rustc_middle::mir::interpret::ScalarSizeMismatch;
|
||||
use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, TyAndLayout};
|
||||
|
|
|
|||
|
|
@ -2,10 +2,9 @@
|
|||
//! into a place.
|
||||
//! All high-level functions to write to memory work on places as destinations.
|
||||
|
||||
use std::assert_matches::assert_matches;
|
||||
|
||||
use either::{Either, Left, Right};
|
||||
use rustc_abi::{BackendRepr, HasDataLayout, Size};
|
||||
use rustc_data_structures::assert_matches;
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_middle::ty::layout::TyAndLayout;
|
||||
use rustc_middle::{bug, mir, span_bug};
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
// A fresh reference was created, make sure it gets retagged.
|
||||
let val = M::retag_ptr_value(
|
||||
self,
|
||||
if borrow_kind.allows_two_phase_borrow() {
|
||||
if borrow_kind.is_two_phase_borrow() {
|
||||
mir::RetagKind::TwoPhase
|
||||
} else {
|
||||
mir::RetagKind::Default
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
// tidy-alphabetical-start
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![feature(array_try_map)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
|
|
|
|||
|
|
@ -28,3 +28,18 @@ macro_rules! define_stable_id_collections {
|
|||
pub type $entry_name<'a, T> = $crate::fx::IndexEntry<'a, $key, T>;
|
||||
};
|
||||
}
|
||||
|
||||
pub mod default {
|
||||
use super::{FxBuildHasher, FxHashMap, FxHashSet};
|
||||
|
||||
// FIXME: These two functions will become unnecessary after
|
||||
// <https://github.com/rust-lang/rustc-hash/pull/63> lands and we start using the corresponding
|
||||
// `rustc-hash` version. After that we can use `Default::default()` instead.
|
||||
pub const fn fx_hash_map<K, V>() -> FxHashMap<K, V> {
|
||||
FxHashMap::with_hasher(FxBuildHasher)
|
||||
}
|
||||
|
||||
pub const fn fx_hash_set<V>() -> FxHashSet<V> {
|
||||
FxHashSet::with_hasher(FxBuildHasher)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
//! Typical examples would include: minimum element in SCC, maximum element
|
||||
//! reachable from it, etc.
|
||||
|
||||
use std::assert_matches::debug_assert_matches;
|
||||
use std::fmt::Debug;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::Range;
|
||||
|
|
@ -16,6 +15,7 @@ use std::ops::Range;
|
|||
use rustc_index::{Idx, IndexSlice, IndexVec};
|
||||
use tracing::{debug, instrument, trace};
|
||||
|
||||
use crate::debug_assert_matches;
|
||||
use crate::fx::FxHashSet;
|
||||
use crate::graph::vec_graph::VecGraph;
|
||||
use crate::graph::{DirectedGraph, NumEdges, Successors};
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@
|
|||
#![feature(assert_matches)]
|
||||
#![feature(auto_traits)]
|
||||
#![feature(cfg_select)]
|
||||
#![feature(const_default)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(dropck_eyepatch)]
|
||||
#![feature(extend_one)]
|
||||
|
|
@ -36,6 +38,11 @@
|
|||
#![feature(unwrap_infallible)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
// Temporarily re-export `assert_matches!`, so that the rest of the compiler doesn't
|
||||
// have to worry about it being moved to a different module in std during stabilization.
|
||||
// FIXME(#151359): Remove this when `feature(assert_matches)` is stable in stage0.
|
||||
// (This doesn't necessarily need to be fixed during the beta bump itself.)
|
||||
pub use std::assert_matches::{assert_matches, debug_assert_matches};
|
||||
use std::fmt;
|
||||
|
||||
pub use atomic_ref::AtomicRef;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use std::hash::Hash;
|
|||
use std::iter::{Product, Sum};
|
||||
use std::ops::Index;
|
||||
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet};
|
||||
use rustc_macros::{Decodable_NoContext, Encodable_NoContext};
|
||||
|
||||
use crate::fingerprint::Fingerprint;
|
||||
|
|
@ -241,10 +241,10 @@ pub struct UnordSet<V: Eq + Hash> {
|
|||
|
||||
impl<V: Eq + Hash> UnordCollection for UnordSet<V> {}
|
||||
|
||||
impl<V: Eq + Hash> Default for UnordSet<V> {
|
||||
impl<V: Eq + Hash> const Default for UnordSet<V> {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self { inner: FxHashSet::default() }
|
||||
Self { inner: FxHashSet::with_hasher(FxBuildHasher) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -438,10 +438,10 @@ pub struct UnordMap<K: Eq + Hash, V> {
|
|||
|
||||
impl<K: Eq + Hash, V> UnordCollection for UnordMap<K, V> {}
|
||||
|
||||
impl<K: Eq + Hash, V> Default for UnordMap<K, V> {
|
||||
impl<K: Eq + Hash, V> const Default for UnordMap<K, V> {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self { inner: FxHashMap::default() }
|
||||
Self { inner: FxHashMap::with_hasher(FxBuildHasher) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ edition = "2024"
|
|||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
anstyle = "1.0.13"
|
||||
jiff = { version = "0.2.5", default-features = false, features = ["std"] }
|
||||
rustc_abi = { path = "../rustc_abi" }
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
|
|
@ -28,6 +29,7 @@ rustc_incremental = { path = "../rustc_incremental" }
|
|||
rustc_index = { path = "../rustc_index" }
|
||||
rustc_infer = { path = "../rustc_infer" }
|
||||
rustc_interface = { path = "../rustc_interface" }
|
||||
rustc_lexer = { path = "../rustc_lexer" }
|
||||
rustc_lint = { path = "../rustc_lint" }
|
||||
rustc_log = { path = "../rustc_log" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
|
|
|
|||
|
|
@ -97,7 +97,6 @@ impl Expander {
|
|||
/// **Note:** This function doesn't interpret argument 0 in any special way.
|
||||
/// If this function is intended to be used with command line arguments,
|
||||
/// `argv[0]` must be removed prior to calling it manually.
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
pub fn arg_expand_all(early_dcx: &EarlyDiagCtxt, at_args: &[String]) -> Vec<String> {
|
||||
let mut expander = Expander::default();
|
||||
let mut result = Ok(());
|
||||
|
|
|
|||
159
compiler/rustc_driver_impl/src/highlighter.rs
Normal file
159
compiler/rustc_driver_impl/src/highlighter.rs
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
//! This module provides a syntax highlighter for Rust code.
|
||||
//! It is used by the `rustc --explain` command.
|
||||
//!
|
||||
//! The syntax highlighter uses `rustc_lexer`'s `tokenize`
|
||||
//! function to parse the Rust code into a `Vec` of tokens.
|
||||
//! The highlighter then highlights the tokens in the `Vec`,
|
||||
//! and writes the highlighted output to the buffer.
|
||||
use std::io::{self, Write};
|
||||
|
||||
use anstyle::{AnsiColor, Color, Effects, Style};
|
||||
use rustc_lexer::{LiteralKind, strip_shebang, tokenize};
|
||||
|
||||
const PRIMITIVE_TYPES: &'static [&str] = &[
|
||||
"i8", "i16", "i32", "i64", "i128", "isize", // signed integers
|
||||
"u8", "u16", "u32", "u64", "u128", "usize", // unsigned integers
|
||||
"f32", "f64", // floating point
|
||||
"char", "bool", // others
|
||||
];
|
||||
|
||||
const KEYWORDS: &'static [&str] = &[
|
||||
"static", "struct", "super", "trait", "true", "type", "unsafe", "use", "where", "while", "as",
|
||||
"async", "await", "break", "const", "continue", "crate", "dyn", "else", "enum", "extern",
|
||||
"false", "fn", "for", "if", "impl", "in", "let", "loop", "match", "mod", "move", "mut", "pub",
|
||||
"ref",
|
||||
];
|
||||
|
||||
const STR_LITERAL_COLOR: AnsiColor = AnsiColor::Green;
|
||||
const OTHER_LITERAL_COLOR: AnsiColor = AnsiColor::BrightRed;
|
||||
const DERIVE_COLOR: AnsiColor = AnsiColor::BrightRed;
|
||||
const KEYWORD_COLOR: AnsiColor = AnsiColor::BrightMagenta;
|
||||
const TYPE_COLOR: AnsiColor = AnsiColor::Yellow;
|
||||
const FUNCTION_COLOR: AnsiColor = AnsiColor::Blue;
|
||||
const USE_COLOR: AnsiColor = AnsiColor::BrightMagenta;
|
||||
const PRIMITIVE_TYPE_COLOR: AnsiColor = AnsiColor::Cyan;
|
||||
|
||||
/// Highlight a Rust code string and write the highlighted
|
||||
/// output to the buffer. It serves as a wrapper around
|
||||
/// `Highlighter::highlight_rustc_lexer`. It is passed to
|
||||
/// `write_anstream_buf` in the `lib.rs` file.
|
||||
pub fn highlight(code: &str, buf: &mut Vec<u8>) -> io::Result<()> {
|
||||
let mut highlighter = Highlighter::default();
|
||||
highlighter.highlight_rustc_lexer(code, buf)
|
||||
}
|
||||
|
||||
/// A syntax highlighter for Rust code
|
||||
/// It is used by the `rustc --explain` command.
|
||||
#[derive(Default)]
|
||||
pub struct Highlighter {
|
||||
/// Used to track if the previous token was a token
|
||||
/// that warrants the next token to be colored differently
|
||||
///
|
||||
/// For example, the keyword `fn` requires the next token
|
||||
/// (the function name) to be colored differently.
|
||||
prev_was_special: bool,
|
||||
/// Used to track the length of tokens that have been
|
||||
/// written so far. This is used to find the original
|
||||
/// lexeme for a token from the code string.
|
||||
len_accum: usize,
|
||||
}
|
||||
|
||||
impl Highlighter {
|
||||
/// Create a new highlighter
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Highlight a Rust code string and write the highlighted
|
||||
/// output to the buffer.
|
||||
pub fn highlight_rustc_lexer(&mut self, code: &str, buf: &mut Vec<u8>) -> io::Result<()> {
|
||||
use rustc_lexer::TokenKind;
|
||||
|
||||
// Remove shebang from code string
|
||||
let stripped_idx = strip_shebang(code).unwrap_or(0);
|
||||
let stripped_code = &code[stripped_idx..];
|
||||
self.len_accum = stripped_idx;
|
||||
let len_accum = &mut self.len_accum;
|
||||
let tokens = tokenize(stripped_code, rustc_lexer::FrontmatterAllowed::No);
|
||||
for token in tokens {
|
||||
let len = token.len as usize;
|
||||
// If the previous token was a special token, and this token is
|
||||
// not a whitespace token, then it should be colored differently
|
||||
let token_str = &code[*len_accum..*len_accum + len];
|
||||
if self.prev_was_special {
|
||||
if token_str != " " {
|
||||
self.prev_was_special = false;
|
||||
}
|
||||
let style = Style::new().fg_color(Some(Color::Ansi(AnsiColor::Blue)));
|
||||
write!(buf, "{style}{token_str}{style:#}")?;
|
||||
*len_accum += len;
|
||||
continue;
|
||||
}
|
||||
match token.kind {
|
||||
TokenKind::Ident => {
|
||||
let mut style = Style::new();
|
||||
// Match if an identifier is a (well-known) keyword
|
||||
if KEYWORDS.contains(&token_str) {
|
||||
if token_str == "fn" {
|
||||
self.prev_was_special = true;
|
||||
}
|
||||
style = style.fg_color(Some(Color::Ansi(KEYWORD_COLOR)));
|
||||
}
|
||||
// The `use` keyword is colored differently
|
||||
if matches!(token_str, "use") {
|
||||
style = style.fg_color(Some(Color::Ansi(USE_COLOR)));
|
||||
}
|
||||
// This heuristic test is to detect if the identifier is
|
||||
// a function call. If it is, then the function identifier is
|
||||
// colored differently.
|
||||
if code[*len_accum..*len_accum + len + 1].ends_with('(') {
|
||||
style = style.fg_color(Some(Color::Ansi(FUNCTION_COLOR)));
|
||||
}
|
||||
// The `derive` keyword is colored differently.
|
||||
if token_str == "derive" {
|
||||
style = style.fg_color(Some(Color::Ansi(DERIVE_COLOR)));
|
||||
}
|
||||
// This heuristic test is to detect if the identifier is
|
||||
// a type. If it is, then the identifier is colored differently.
|
||||
if matches!(token_str.chars().next().map(|c| c.is_uppercase()), Some(true)) {
|
||||
style = style.fg_color(Some(Color::Ansi(TYPE_COLOR)));
|
||||
}
|
||||
// This if statement is to detect if the identifier is a primitive type.
|
||||
if PRIMITIVE_TYPES.contains(&token_str) {
|
||||
style = style.fg_color(Some(Color::Ansi(PRIMITIVE_TYPE_COLOR)));
|
||||
}
|
||||
write!(buf, "{style}{token_str}{style:#}")?;
|
||||
}
|
||||
|
||||
// Color literals
|
||||
TokenKind::Literal { kind, suffix_start: _ } => {
|
||||
// Strings -> Green
|
||||
// Chars -> Green
|
||||
// Raw strings -> Green
|
||||
// C strings -> Green
|
||||
// Byte Strings -> Green
|
||||
// Other literals -> Bright Red (Orage-esque)
|
||||
let style = match kind {
|
||||
LiteralKind::Str { terminated: _ }
|
||||
| LiteralKind::Char { terminated: _ }
|
||||
| LiteralKind::RawStr { n_hashes: _ }
|
||||
| LiteralKind::CStr { terminated: _ } => {
|
||||
Style::new().fg_color(Some(Color::Ansi(STR_LITERAL_COLOR)))
|
||||
}
|
||||
_ => Style::new().fg_color(Some(Color::Ansi(OTHER_LITERAL_COLOR))),
|
||||
};
|
||||
write!(buf, "{style}{token_str}{style:#}")?;
|
||||
}
|
||||
_ => {
|
||||
// All other tokens are dimmed
|
||||
let style = Style::new()
|
||||
.fg_color(Some(Color::Ansi(AnsiColor::BrightWhite)))
|
||||
.effects(Effects::DIMMED);
|
||||
write!(buf, "{style}{token_str}{style:#}")?;
|
||||
}
|
||||
}
|
||||
*len_accum += len;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,6 @@
|
|||
//! This API is completely unstable and subject to change.
|
||||
|
||||
// tidy-alphabetical-start
|
||||
#![allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
#![feature(decl_macro)]
|
||||
#![feature(panic_backtrace_config)]
|
||||
#![feature(panic_update_hook)]
|
||||
|
|
@ -86,6 +85,7 @@ pub mod args;
|
|||
pub mod pretty;
|
||||
#[macro_use]
|
||||
mod print;
|
||||
pub mod highlighter;
|
||||
mod session_diagnostics;
|
||||
|
||||
// Keep the OS parts of this `cfg` in sync with the `cfg` on the `libc`
|
||||
|
|
@ -228,8 +228,10 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send))
|
|||
|
||||
let args = args::arg_expand_all(&default_early_dcx, at_args);
|
||||
|
||||
let Some(matches) = handle_options(&default_early_dcx, &args) else {
|
||||
return;
|
||||
let (matches, help_only) = match handle_options(&default_early_dcx, &args) {
|
||||
HandledOptions::None => return,
|
||||
HandledOptions::Normal(matches) => (matches, false),
|
||||
HandledOptions::HelpOnly(matches) => (matches, true),
|
||||
};
|
||||
|
||||
let sopts = config::build_session_options(&mut default_early_dcx, &matches);
|
||||
|
|
@ -291,12 +293,16 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send))
|
|||
return early_exit();
|
||||
}
|
||||
|
||||
// We have now handled all help options, exit
|
||||
if help_only {
|
||||
return early_exit();
|
||||
}
|
||||
|
||||
if print_crate_info(codegen_backend, sess, has_input) == Compilation::Stop {
|
||||
return early_exit();
|
||||
}
|
||||
|
||||
if !has_input {
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
sess.dcx().fatal("no input filename given"); // this is fatal
|
||||
}
|
||||
|
||||
|
|
@ -521,7 +527,11 @@ fn show_md_content_with_pager(content: &str, color: ColorConfig) {
|
|||
let mdstream = markdown::MdStream::parse_str(content);
|
||||
let bufwtr = markdown::create_stdout_bufwtr();
|
||||
let mut mdbuf = Vec::new();
|
||||
if mdstream.write_anstream_buf(&mut mdbuf).is_ok() { Some((bufwtr, mdbuf)) } else { None }
|
||||
if mdstream.write_anstream_buf(&mut mdbuf, Some(&highlighter::highlight)).is_ok() {
|
||||
Some((bufwtr, mdbuf))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
// Try to print via the pager, pretty output if possible.
|
||||
|
|
@ -608,7 +618,6 @@ fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) {
|
|||
safe_println!("{}", String::from_utf8(v).unwrap());
|
||||
}
|
||||
Input::Str { .. } => {
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
sess.dcx().fatal("cannot list metadata for stdin");
|
||||
}
|
||||
}
|
||||
|
|
@ -835,7 +844,6 @@ fn print_crate_info(
|
|||
sess.apple_deployment_target().fmt_pretty(),
|
||||
)
|
||||
} else {
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
sess.dcx().fatal("only Apple targets currently support deployment version info")
|
||||
}
|
||||
}
|
||||
|
|
@ -1097,7 +1105,7 @@ pub fn describe_flag_categories(early_dcx: &EarlyDiagCtxt, matches: &Matches) ->
|
|||
// Don't handle -W help here, because we might first load additional lints.
|
||||
let debug_flags = matches.opt_strs("Z");
|
||||
if debug_flags.iter().any(|x| *x == "help") {
|
||||
describe_debug_flags();
|
||||
describe_unstable_flags();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1137,8 +1145,8 @@ fn get_backend_from_raw_matches(
|
|||
get_codegen_backend(early_dcx, &sysroot, backend_name, &target)
|
||||
}
|
||||
|
||||
fn describe_debug_flags() {
|
||||
safe_println!("\nAvailable options:\n");
|
||||
fn describe_unstable_flags() {
|
||||
safe_println!("\nAvailable unstable options:\n");
|
||||
print_flag_list("-Z", config::Z_OPTIONS);
|
||||
}
|
||||
|
||||
|
|
@ -1162,6 +1170,16 @@ fn print_flag_list<T>(cmdline_opt: &str, flag_list: &[OptionDesc<T>]) {
|
|||
}
|
||||
}
|
||||
|
||||
pub enum HandledOptions {
|
||||
/// Parsing failed, or we parsed a flag causing an early exit
|
||||
None,
|
||||
/// Successful parsing
|
||||
Normal(getopts::Matches),
|
||||
/// Parsing succeeded, but we received one or more 'help' flags
|
||||
/// The compiler should proceed only until a possible `-W help` flag has been processed
|
||||
HelpOnly(getopts::Matches),
|
||||
}
|
||||
|
||||
/// Process command line options. Emits messages as appropriate. If compilation
|
||||
/// should continue, returns a getopts::Matches object parsed from args,
|
||||
/// otherwise returns `None`.
|
||||
|
|
@ -1189,7 +1207,7 @@ fn print_flag_list<T>(cmdline_opt: &str, flag_list: &[OptionDesc<T>]) {
|
|||
/// This does not need to be `pub` for rustc itself, but @chaosite needs it to
|
||||
/// be public when using rustc as a library, see
|
||||
/// <https://github.com/rust-lang/rust/commit/2b4c33817a5aaecabf4c6598d41e190080ec119e>
|
||||
pub fn handle_options(early_dcx: &EarlyDiagCtxt, args: &[String]) -> Option<getopts::Matches> {
|
||||
pub fn handle_options(early_dcx: &EarlyDiagCtxt, args: &[String]) -> HandledOptions {
|
||||
// Parse with *all* options defined in the compiler, we don't worry about
|
||||
// option stability here we just want to parse as much as possible.
|
||||
let mut options = getopts::Options::new();
|
||||
|
|
@ -1235,26 +1253,69 @@ pub fn handle_options(early_dcx: &EarlyDiagCtxt, args: &[String]) -> Option<geto
|
|||
// (unstable option being used on stable)
|
||||
nightly_options::check_nightly_options(early_dcx, &matches, &config::rustc_optgroups());
|
||||
|
||||
if args.is_empty() || matches.opt_present("h") || matches.opt_present("help") {
|
||||
// Only show unstable options in --help if we accept unstable options.
|
||||
let unstable_enabled = nightly_options::is_unstable_enabled(&matches);
|
||||
let nightly_build = nightly_options::match_is_nightly_build(&matches);
|
||||
usage(matches.opt_present("verbose"), unstable_enabled, nightly_build);
|
||||
return None;
|
||||
// Handle the special case of -Wall.
|
||||
let wall = matches.opt_strs("W");
|
||||
if wall.iter().any(|x| *x == "all") {
|
||||
print_wall_help();
|
||||
return HandledOptions::None;
|
||||
}
|
||||
|
||||
if describe_flag_categories(early_dcx, &matches) {
|
||||
return None;
|
||||
if handle_help(&matches, args) {
|
||||
return HandledOptions::HelpOnly(matches);
|
||||
}
|
||||
|
||||
if matches.opt_strs("C").iter().any(|x| x == "passes=list") {
|
||||
get_backend_from_raw_matches(early_dcx, &matches).print_passes();
|
||||
return HandledOptions::None;
|
||||
}
|
||||
|
||||
if matches.opt_present("version") {
|
||||
version!(early_dcx, "rustc", &matches);
|
||||
return None;
|
||||
return HandledOptions::None;
|
||||
}
|
||||
|
||||
warn_on_confusing_output_filename_flag(early_dcx, &matches, args);
|
||||
|
||||
Some(matches)
|
||||
HandledOptions::Normal(matches)
|
||||
}
|
||||
|
||||
/// Handle help options in the order they are provided, ignoring other flags. Returns if any options were handled
|
||||
/// Handled options:
|
||||
/// - `-h`/`--help`/empty arguments
|
||||
/// - `-Z help`
|
||||
/// - `-C help`
|
||||
/// NOTE: `-W help` is NOT handled here, as additional lints may be loaded.
|
||||
pub fn handle_help(matches: &getopts::Matches, args: &[String]) -> bool {
|
||||
let opt_pos = |opt| matches.opt_positions(opt).first().copied();
|
||||
let opt_help_pos = |opt| {
|
||||
matches
|
||||
.opt_strs_pos(opt)
|
||||
.iter()
|
||||
.filter_map(|(pos, oval)| if oval == "help" { Some(*pos) } else { None })
|
||||
.next()
|
||||
};
|
||||
let help_pos = if args.is_empty() { Some(0) } else { opt_pos("h").or_else(|| opt_pos("help")) };
|
||||
let zhelp_pos = opt_help_pos("Z");
|
||||
let chelp_pos = opt_help_pos("C");
|
||||
let print_help = || {
|
||||
// Only show unstable options in --help if we accept unstable options.
|
||||
let unstable_enabled = nightly_options::is_unstable_enabled(&matches);
|
||||
let nightly_build = nightly_options::match_is_nightly_build(&matches);
|
||||
usage(matches.opt_present("verbose"), unstable_enabled, nightly_build);
|
||||
};
|
||||
|
||||
let mut helps = [
|
||||
(help_pos, &print_help as &dyn Fn()),
|
||||
(zhelp_pos, &describe_unstable_flags),
|
||||
(chelp_pos, &describe_codegen_flags),
|
||||
];
|
||||
helps.sort_by_key(|(pos, _)| pos.clone());
|
||||
let mut printed_any = false;
|
||||
for printer in helps.iter().filter_map(|(pos, func)| pos.is_some().then_some(func)) {
|
||||
printer();
|
||||
printed_any = true;
|
||||
}
|
||||
printed_any
|
||||
}
|
||||
|
||||
/// Warn if `-o` is used without a space between the flag name and the value
|
||||
|
|
|
|||
|
|
@ -244,13 +244,6 @@ type FluentId = Cow<'static, str>;
|
|||
pub enum SubdiagMessage {
|
||||
/// Non-translatable diagnostic message.
|
||||
Str(Cow<'static, str>),
|
||||
/// Translatable message which has already been translated eagerly.
|
||||
///
|
||||
/// Some diagnostics have repeated subdiagnostics where the same interpolated variables would
|
||||
/// be instantiated multiple times with different values. These subdiagnostics' messages
|
||||
/// are translated when they are added to the parent diagnostic, producing this variant of
|
||||
/// `DiagMessage`.
|
||||
Translated(Cow<'static, str>),
|
||||
/// Identifier of a Fluent message. Instances of this variant are generated by the
|
||||
/// `Subdiagnostic` derive.
|
||||
FluentIdentifier(FluentId),
|
||||
|
|
@ -285,15 +278,13 @@ impl From<Cow<'static, str>> for SubdiagMessage {
|
|||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
|
||||
#[rustc_diagnostic_item = "DiagMessage"]
|
||||
pub enum DiagMessage {
|
||||
/// Non-translatable diagnostic message.
|
||||
Str(Cow<'static, str>),
|
||||
/// Translatable message which has been already translated.
|
||||
/// Non-translatable diagnostic message or a message that has been translated eagerly.
|
||||
///
|
||||
/// Some diagnostics have repeated subdiagnostics where the same interpolated variables would
|
||||
/// be instantiated multiple times with different values. These subdiagnostics' messages
|
||||
/// are translated when they are added to the parent diagnostic, producing this variant of
|
||||
/// `DiagMessage`.
|
||||
Translated(Cow<'static, str>),
|
||||
/// are translated when they are added to the parent diagnostic. This is one of the ways
|
||||
/// this variant of `DiagMessage` is produced.
|
||||
Str(Cow<'static, str>),
|
||||
/// Identifier for a Fluent message (with optional attribute) corresponding to the diagnostic
|
||||
/// message. Yet to be translated.
|
||||
///
|
||||
|
|
@ -311,7 +302,6 @@ impl DiagMessage {
|
|||
pub fn with_subdiagnostic_message(&self, sub: SubdiagMessage) -> Self {
|
||||
let attr = match sub {
|
||||
SubdiagMessage::Str(s) => return DiagMessage::Str(s),
|
||||
SubdiagMessage::Translated(s) => return DiagMessage::Translated(s),
|
||||
SubdiagMessage::FluentIdentifier(id) => {
|
||||
return DiagMessage::FluentIdentifier(id, None);
|
||||
}
|
||||
|
|
@ -320,7 +310,6 @@ impl DiagMessage {
|
|||
|
||||
match self {
|
||||
DiagMessage::Str(s) => DiagMessage::Str(s.clone()),
|
||||
DiagMessage::Translated(s) => DiagMessage::Translated(s.clone()),
|
||||
DiagMessage::FluentIdentifier(id, _) => {
|
||||
DiagMessage::FluentIdentifier(id.clone(), Some(attr))
|
||||
}
|
||||
|
|
@ -329,7 +318,7 @@ impl DiagMessage {
|
|||
|
||||
pub fn as_str(&self) -> Option<&str> {
|
||||
match self {
|
||||
DiagMessage::Translated(s) | DiagMessage::Str(s) => Some(s),
|
||||
DiagMessage::Str(s) => Some(s),
|
||||
DiagMessage::FluentIdentifier(_, _) => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -360,7 +349,6 @@ impl From<DiagMessage> for SubdiagMessage {
|
|||
fn from(val: DiagMessage) -> Self {
|
||||
match val {
|
||||
DiagMessage::Str(s) => SubdiagMessage::Str(s),
|
||||
DiagMessage::Translated(s) => SubdiagMessage::Translated(s),
|
||||
DiagMessage::FluentIdentifier(id, None) => SubdiagMessage::FluentIdentifier(id),
|
||||
// There isn't really a sensible behaviour for this because it loses information but
|
||||
// this is the most sensible of the behaviours.
|
||||
|
|
|
|||
|
|
@ -538,7 +538,6 @@ macro_rules! with_fn {
|
|||
}
|
||||
|
||||
impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn new(dcx: DiagCtxtHandle<'a>, level: Level, message: impl Into<DiagMessage>) -> Self {
|
||||
Self::new_diagnostic(dcx, DiagInner::new(level, message))
|
||||
|
|
@ -566,7 +565,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
///
|
||||
/// In the meantime, though, callsites are required to deal with the "bug"
|
||||
/// locally in whichever way makes the most sense.
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn downgrade_to_delayed_bug(&mut self) {
|
||||
assert!(
|
||||
|
|
@ -584,7 +582,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
/// This function still gives an emission guarantee, the guarantee is now just that it exits fatally.
|
||||
/// For delayed bugs this is different, since those are buffered. If we upgrade one to fatal, another
|
||||
/// might now be ignored.
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn upgrade_to_fatal(mut self) -> Diag<'a, FatalAbort> {
|
||||
assert!(
|
||||
|
|
@ -613,7 +610,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
/// the diagnostic was constructed. However, the label span is *not* considered a
|
||||
/// ["primary span"][`MultiSpan`]; only the `Span` supplied when creating the diagnostic is
|
||||
/// primary.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn span_label(&mut self, span: Span, label: impl Into<SubdiagMessage>) -> &mut Self {
|
||||
let msg = self.subdiagnostic_message_to_diagnostic_message(label);
|
||||
self.span.push_span_label(span, msg);
|
||||
|
|
@ -623,7 +619,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
with_fn! { with_span_labels,
|
||||
/// Labels all the given spans with the provided label.
|
||||
/// See [`Self::span_label()`] for more information.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn span_labels(&mut self, spans: impl IntoIterator<Item = Span>, label: &str) -> &mut Self {
|
||||
for span in spans {
|
||||
self.span_label(span, label.to_string());
|
||||
|
|
@ -631,7 +626,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
self
|
||||
} }
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn replace_span_with(&mut self, after: Span, keep_label: bool) -> &mut Self {
|
||||
let before = self.span.clone();
|
||||
self.span(after);
|
||||
|
|
@ -647,7 +641,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
self
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn note_expected_found(
|
||||
&mut self,
|
||||
expected_label: &str,
|
||||
|
|
@ -665,7 +658,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn note_expected_found_extra(
|
||||
&mut self,
|
||||
expected_label: &str,
|
||||
|
|
@ -711,7 +703,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
self
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn note_trait_signature(&mut self, name: Symbol, signature: String) -> &mut Self {
|
||||
self.highlighted_note(vec![
|
||||
StringPart::normal(format!("`{name}` from trait: `")),
|
||||
|
|
@ -723,19 +714,16 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
|
||||
with_fn! { with_note,
|
||||
/// Add a note attached to this diagnostic.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn note(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
|
||||
self.sub(Level::Note, msg, MultiSpan::new());
|
||||
self
|
||||
} }
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn highlighted_note(&mut self, msg: Vec<StringPart>) -> &mut Self {
|
||||
self.sub_with_highlights(Level::Note, msg, MultiSpan::new());
|
||||
self
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn highlighted_span_note(
|
||||
&mut self,
|
||||
span: impl Into<MultiSpan>,
|
||||
|
|
@ -746,7 +734,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
}
|
||||
|
||||
/// This is like [`Diag::note()`], but it's only printed once.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn note_once(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
|
||||
self.sub(Level::OnceNote, msg, MultiSpan::new());
|
||||
self
|
||||
|
|
@ -755,7 +742,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
with_fn! { with_span_note,
|
||||
/// Prints the span with a note above it.
|
||||
/// This is like [`Diag::note()`], but it gets its own span.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn span_note(
|
||||
&mut self,
|
||||
sp: impl Into<MultiSpan>,
|
||||
|
|
@ -767,7 +753,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
|
||||
/// Prints the span with a note above it.
|
||||
/// This is like [`Diag::note_once()`], but it gets its own span.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn span_note_once<S: Into<MultiSpan>>(
|
||||
&mut self,
|
||||
sp: S,
|
||||
|
|
@ -779,7 +764,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
|
||||
with_fn! { with_warn,
|
||||
/// Add a warning attached to this diagnostic.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn warn(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
|
||||
self.sub(Level::Warning, msg, MultiSpan::new());
|
||||
self
|
||||
|
|
@ -787,7 +771,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
|
||||
/// Prints the span with a warning above it.
|
||||
/// This is like [`Diag::warn()`], but it gets its own span.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn span_warn<S: Into<MultiSpan>>(
|
||||
&mut self,
|
||||
sp: S,
|
||||
|
|
@ -799,28 +782,24 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
|
||||
with_fn! { with_help,
|
||||
/// Add a help message attached to this diagnostic.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn help(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
|
||||
self.sub(Level::Help, msg, MultiSpan::new());
|
||||
self
|
||||
} }
|
||||
|
||||
/// This is like [`Diag::help()`], but it's only printed once.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn help_once(&mut self, msg: impl Into<SubdiagMessage>) -> &mut Self {
|
||||
self.sub(Level::OnceHelp, msg, MultiSpan::new());
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a help message attached to this diagnostic with a customizable highlighted message.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn highlighted_help(&mut self, msg: Vec<StringPart>) -> &mut Self {
|
||||
self.sub_with_highlights(Level::Help, msg, MultiSpan::new());
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a help message attached to this diagnostic with a customizable highlighted message.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn highlighted_span_help(
|
||||
&mut self,
|
||||
span: impl Into<MultiSpan>,
|
||||
|
|
@ -833,7 +812,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
with_fn! { with_span_help,
|
||||
/// Prints the span with some help above it.
|
||||
/// This is like [`Diag::help()`], but it gets its own span.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn span_help(
|
||||
&mut self,
|
||||
sp: impl Into<MultiSpan>,
|
||||
|
|
@ -846,7 +824,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
/// Disallow attaching suggestions to this diagnostic.
|
||||
/// Any suggestions attached e.g. with the `span_suggestion_*` methods
|
||||
/// (before and after the call to `disable_suggestions`) will be ignored.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn disable_suggestions(&mut self) -> &mut Self {
|
||||
self.suggestions = Suggestions::Disabled;
|
||||
self
|
||||
|
|
@ -856,7 +833,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
///
|
||||
/// Suggestions added before the call to `.seal_suggestions()` will be preserved
|
||||
/// and new suggestions will be ignored.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn seal_suggestions(&mut self) -> &mut Self {
|
||||
if let Suggestions::Enabled(suggestions) = &mut self.suggestions {
|
||||
let suggestions_slice = std::mem::take(suggestions).into_boxed_slice();
|
||||
|
|
@ -869,7 +845,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
///
|
||||
/// A new suggestion is added if suggestions are enabled for this diagnostic.
|
||||
/// Otherwise, they are ignored.
|
||||
#[rustc_lint_diagnostics]
|
||||
fn push_suggestion(&mut self, suggestion: CodeSuggestion) {
|
||||
for subst in &suggestion.substitutions {
|
||||
for part in &subst.parts {
|
||||
|
|
@ -890,7 +865,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
with_fn! { with_multipart_suggestion,
|
||||
/// Show a suggestion that has multiple parts to it.
|
||||
/// In other words, multiple changes need to be applied as part of this suggestion.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn multipart_suggestion(
|
||||
&mut self,
|
||||
msg: impl Into<SubdiagMessage>,
|
||||
|
|
@ -907,7 +881,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
|
||||
/// Show a suggestion that has multiple parts to it, always as its own subdiagnostic.
|
||||
/// In other words, multiple changes need to be applied as part of this suggestion.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn multipart_suggestion_verbose(
|
||||
&mut self,
|
||||
msg: impl Into<SubdiagMessage>,
|
||||
|
|
@ -923,7 +896,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
}
|
||||
|
||||
/// [`Diag::multipart_suggestion()`] but you can set the [`SuggestionStyle`].
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn multipart_suggestion_with_style(
|
||||
&mut self,
|
||||
msg: impl Into<SubdiagMessage>,
|
||||
|
|
@ -966,7 +938,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
/// be from the message, showing the span label inline would be visually unpleasant
|
||||
/// (marginally overlapping spans or multiline spans) and showing the snippet window wouldn't
|
||||
/// improve understandability.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn tool_only_multipart_suggestion(
|
||||
&mut self,
|
||||
msg: impl Into<SubdiagMessage>,
|
||||
|
|
@ -999,7 +970,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
/// * may contain a name of a function, variable, or type, but not whole expressions
|
||||
///
|
||||
/// See [`CodeSuggestion`] for more information.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn span_suggestion(
|
||||
&mut self,
|
||||
sp: Span,
|
||||
|
|
@ -1018,7 +988,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
} }
|
||||
|
||||
/// [`Diag::span_suggestion()`] but you can set the [`SuggestionStyle`].
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn span_suggestion_with_style(
|
||||
&mut self,
|
||||
sp: Span,
|
||||
|
|
@ -1044,7 +1013,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
|
||||
with_fn! { with_span_suggestion_verbose,
|
||||
/// Always show the suggested change.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn span_suggestion_verbose(
|
||||
&mut self,
|
||||
sp: Span,
|
||||
|
|
@ -1065,7 +1033,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
with_fn! { with_span_suggestions,
|
||||
/// Prints out a message with multiple suggested edits of the code.
|
||||
/// See also [`Diag::span_suggestion()`].
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn span_suggestions(
|
||||
&mut self,
|
||||
sp: Span,
|
||||
|
|
@ -1082,7 +1049,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
)
|
||||
} }
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn span_suggestions_with_style(
|
||||
&mut self,
|
||||
sp: Span,
|
||||
|
|
@ -1113,7 +1079,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
/// Prints out a message with multiple suggested edits of the code, where each edit consists of
|
||||
/// multiple parts.
|
||||
/// See also [`Diag::multipart_suggestion()`].
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn multipart_suggestions(
|
||||
&mut self,
|
||||
msg: impl Into<SubdiagMessage>,
|
||||
|
|
@ -1160,7 +1125,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
/// inline, it will only show the message and not the suggestion.
|
||||
///
|
||||
/// See [`CodeSuggestion`] for more information.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn span_suggestion_short(
|
||||
&mut self,
|
||||
sp: Span,
|
||||
|
|
@ -1184,7 +1148,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
/// be from the message, showing the span label inline would be visually unpleasant
|
||||
/// (marginally overlapping spans or multiline spans) and showing the snippet window wouldn't
|
||||
/// improve understandability.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn span_suggestion_hidden(
|
||||
&mut self,
|
||||
sp: Span,
|
||||
|
|
@ -1207,7 +1170,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
///
|
||||
/// This is intended to be used for suggestions that are *very* obvious in what the changes
|
||||
/// need to be from the message, but we still want other tools to be able to apply them.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn tool_only_span_suggestion(
|
||||
&mut self,
|
||||
sp: Span,
|
||||
|
|
@ -1229,7 +1191,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
/// [rustc_macros::Subdiagnostic]). Performs eager translation of any translatable messages
|
||||
/// used in the subdiagnostic, so suitable for use with repeated messages (i.e. re-use of
|
||||
/// interpolated variables).
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn subdiagnostic(&mut self, subdiagnostic: impl Subdiagnostic) -> &mut Self {
|
||||
subdiagnostic.add_to_diag(self);
|
||||
self
|
||||
|
|
@ -1248,7 +1209,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
|
||||
with_fn! { with_span,
|
||||
/// Add a span.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn span(&mut self, sp: impl Into<MultiSpan>) -> &mut Self {
|
||||
self.span = sp.into();
|
||||
if let Some(span) = self.span.primary_span() {
|
||||
|
|
@ -1257,7 +1217,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
self
|
||||
} }
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn is_lint(&mut self, name: String, has_future_breakage: bool) -> &mut Self {
|
||||
self.is_lint = Some(IsLint { name, has_future_breakage });
|
||||
self
|
||||
|
|
@ -1265,7 +1224,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
|
||||
with_fn! { with_code,
|
||||
/// Add an error code.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn code(&mut self, code: ErrCode) -> &mut Self {
|
||||
self.code = Some(code);
|
||||
self
|
||||
|
|
@ -1273,7 +1231,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
|
||||
with_fn! { with_lint_id,
|
||||
/// Add an argument.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn lint_id(
|
||||
&mut self,
|
||||
id: LintExpectationId,
|
||||
|
|
@ -1284,7 +1241,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
|
||||
with_fn! { with_primary_message,
|
||||
/// Add a primary message.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn primary_message(&mut self, msg: impl Into<DiagMessage>) -> &mut Self {
|
||||
self.messages[0] = (msg.into(), Style::NoStyle);
|
||||
self
|
||||
|
|
@ -1292,7 +1248,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
|
|||
|
||||
with_fn! { with_arg,
|
||||
/// Add an argument.
|
||||
#[rustc_lint_diagnostics]
|
||||
pub fn arg(
|
||||
&mut self,
|
||||
name: impl Into<DiagArgName>,
|
||||
|
|
|
|||
|
|
@ -4,9 +4,7 @@
|
|||
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![allow(rustc::direct_use_of_rustc_type_ir)]
|
||||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![cfg_attr(bootstrap, feature(array_windows))]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(associated_type_defaults)]
|
||||
|
|
@ -23,7 +21,6 @@
|
|||
|
||||
extern crate self as rustc_errors;
|
||||
|
||||
use std::assert_matches::assert_matches;
|
||||
use std::backtrace::{Backtrace, BacktraceStatus};
|
||||
use std::borrow::Cow;
|
||||
use std::cell::Cell;
|
||||
|
|
@ -55,10 +52,10 @@ pub use diagnostic_impls::{
|
|||
};
|
||||
pub use emitter::ColorConfig;
|
||||
use emitter::{ConfusionType, DynEmitter, Emitter, detect_confusion_type, is_different};
|
||||
use rustc_data_structures::AtomicRef;
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_data_structures::stable_hasher::StableHasher;
|
||||
use rustc_data_structures::sync::{DynSend, Lock};
|
||||
use rustc_data_structures::{AtomicRef, assert_matches};
|
||||
pub use rustc_error_messages::{
|
||||
DiagArg, DiagArgFromDisplay, DiagArgName, DiagArgValue, DiagMessage, FluentBundle, IntoDiagArg,
|
||||
LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagMessage,
|
||||
|
|
@ -1217,22 +1214,16 @@ impl<'a> DiagCtxtHandle<'a> {
|
|||
// Functions beginning with `struct_`/`create_` create a diagnostic. Other
|
||||
// functions create and emit a diagnostic all in one go.
|
||||
impl<'a> DiagCtxtHandle<'a> {
|
||||
// No `#[rustc_lint_diagnostics]` and no `impl Into<DiagMessage>` because bug messages aren't
|
||||
// user-facing.
|
||||
#[track_caller]
|
||||
pub fn struct_bug(self, msg: impl Into<Cow<'static, str>>) -> Diag<'a, BugAbort> {
|
||||
Diag::new(self, Bug, msg.into())
|
||||
}
|
||||
|
||||
// No `#[rustc_lint_diagnostics]` and no `impl Into<DiagMessage>` because bug messages aren't
|
||||
// user-facing.
|
||||
#[track_caller]
|
||||
pub fn bug(self, msg: impl Into<Cow<'static, str>>) -> ! {
|
||||
self.struct_bug(msg).emit()
|
||||
}
|
||||
|
||||
// No `#[rustc_lint_diagnostics]` and no `impl Into<DiagMessage>` because bug messages aren't
|
||||
// user-facing.
|
||||
#[track_caller]
|
||||
pub fn struct_span_bug(
|
||||
self,
|
||||
|
|
@ -1242,8 +1233,6 @@ impl<'a> DiagCtxtHandle<'a> {
|
|||
self.struct_bug(msg).with_span(span)
|
||||
}
|
||||
|
||||
// No `#[rustc_lint_diagnostics]` and no `impl Into<DiagMessage>` because bug messages aren't
|
||||
// user-facing.
|
||||
#[track_caller]
|
||||
pub fn span_bug(self, span: impl Into<MultiSpan>, msg: impl Into<Cow<'static, str>>) -> ! {
|
||||
self.struct_span_bug(span, msg.into()).emit()
|
||||
|
|
@ -1259,19 +1248,16 @@ impl<'a> DiagCtxtHandle<'a> {
|
|||
self.create_bug(bug).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_fatal(self, msg: impl Into<DiagMessage>) -> Diag<'a, FatalAbort> {
|
||||
Diag::new(self, Fatal, msg)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn fatal(self, msg: impl Into<DiagMessage>) -> ! {
|
||||
self.struct_fatal(msg).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_span_fatal(
|
||||
self,
|
||||
|
|
@ -1281,7 +1267,6 @@ impl<'a> DiagCtxtHandle<'a> {
|
|||
self.struct_fatal(msg).with_span(span)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn span_fatal(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) -> ! {
|
||||
self.struct_span_fatal(span, msg).emit()
|
||||
|
|
@ -1311,19 +1296,16 @@ impl<'a> DiagCtxtHandle<'a> {
|
|||
}
|
||||
|
||||
// FIXME: This method should be removed (every error should have an associated error code).
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_err(self, msg: impl Into<DiagMessage>) -> Diag<'a> {
|
||||
Diag::new(self, Error, msg)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn err(self, msg: impl Into<DiagMessage>) -> ErrorGuaranteed {
|
||||
self.struct_err(msg).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_span_err(
|
||||
self,
|
||||
|
|
@ -1333,7 +1315,6 @@ impl<'a> DiagCtxtHandle<'a> {
|
|||
self.struct_err(msg).with_span(span)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn span_err(
|
||||
self,
|
||||
|
|
@ -1354,9 +1335,6 @@ impl<'a> DiagCtxtHandle<'a> {
|
|||
}
|
||||
|
||||
/// Ensures that an error is printed. See [`Level::DelayedBug`].
|
||||
//
|
||||
// No `#[rustc_lint_diagnostics]` and no `impl Into<DiagMessage>` because bug messages aren't
|
||||
// user-facing.
|
||||
#[track_caller]
|
||||
pub fn delayed_bug(self, msg: impl Into<Cow<'static, str>>) -> ErrorGuaranteed {
|
||||
Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg.into()).emit()
|
||||
|
|
@ -1366,9 +1344,6 @@ impl<'a> DiagCtxtHandle<'a> {
|
|||
///
|
||||
/// Note: this function used to be called `delay_span_bug`. It was renamed
|
||||
/// to match similar functions like `span_err`, `span_warn`, etc.
|
||||
//
|
||||
// No `#[rustc_lint_diagnostics]` and no `impl Into<DiagMessage>` because bug messages aren't
|
||||
// user-facing.
|
||||
#[track_caller]
|
||||
pub fn span_delayed_bug(
|
||||
self,
|
||||
|
|
@ -1378,19 +1353,16 @@ impl<'a> DiagCtxtHandle<'a> {
|
|||
Diag::<ErrorGuaranteed>::new(self, DelayedBug, msg.into()).with_span(sp).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_warn(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
|
||||
Diag::new(self, Warning, msg)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn warn(self, msg: impl Into<DiagMessage>) {
|
||||
self.struct_warn(msg).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_span_warn(
|
||||
self,
|
||||
|
|
@ -1400,7 +1372,6 @@ impl<'a> DiagCtxtHandle<'a> {
|
|||
self.struct_warn(msg).with_span(span)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn span_warn(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
|
||||
self.struct_span_warn(span, msg).emit()
|
||||
|
|
@ -1416,19 +1387,16 @@ impl<'a> DiagCtxtHandle<'a> {
|
|||
self.create_warn(warning).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_note(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
|
||||
Diag::new(self, Note, msg)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn note(&self, msg: impl Into<DiagMessage>) {
|
||||
self.struct_note(msg).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_span_note(
|
||||
self,
|
||||
|
|
@ -1438,7 +1406,6 @@ impl<'a> DiagCtxtHandle<'a> {
|
|||
self.struct_note(msg).with_span(span)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn span_note(self, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
|
||||
self.struct_span_note(span, msg).emit()
|
||||
|
|
@ -1454,25 +1421,21 @@ impl<'a> DiagCtxtHandle<'a> {
|
|||
self.create_note(note).emit()
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_help(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
|
||||
Diag::new(self, Help, msg)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_failure_note(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
|
||||
Diag::new(self, FailureNote, msg)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_allow(self, msg: impl Into<DiagMessage>) -> Diag<'a, ()> {
|
||||
Diag::new(self, Allow, msg)
|
||||
}
|
||||
|
||||
#[rustc_lint_diagnostics]
|
||||
#[track_caller]
|
||||
pub fn struct_expect(self, msg: impl Into<DiagMessage>, id: LintExpectationId) -> Diag<'a, ()> {
|
||||
Diag::new(self, Expect, msg).with_lint_id(id)
|
||||
|
|
@ -1745,7 +1708,7 @@ impl DiagCtxtInner {
|
|||
message: DiagMessage,
|
||||
args: impl Iterator<Item = DiagArg<'a>>,
|
||||
) -> SubdiagMessage {
|
||||
SubdiagMessage::Translated(Cow::from(self.eagerly_translate_to_string(message, args)))
|
||||
SubdiagMessage::Str(Cow::from(self.eagerly_translate_to_string(message, args)))
|
||||
}
|
||||
|
||||
/// Translate `message` eagerly with `args` to `String`.
|
||||
|
|
|
|||
|
|
@ -18,9 +18,14 @@ impl<'a> MdStream<'a> {
|
|||
parse::entrypoint(s)
|
||||
}
|
||||
|
||||
/// Write formatted output to an anstream buffer
|
||||
pub fn write_anstream_buf(&self, buf: &mut Vec<u8>) -> io::Result<()> {
|
||||
term::entrypoint(self, buf)
|
||||
/// Write formatted output to a stdout buffer, optionally with
|
||||
/// a formatter for code blocks
|
||||
pub fn write_anstream_buf(
|
||||
&self,
|
||||
buf: &mut Vec<u8>,
|
||||
formatter: Option<&(dyn Fn(&str, &mut Vec<u8>) -> io::Result<()> + 'static)>,
|
||||
) -> io::Result<()> {
|
||||
term::entrypoint(self, buf, formatter)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,29 +12,33 @@ thread_local! {
|
|||
static CURSOR: Cell<usize> = const { Cell::new(0) };
|
||||
/// Width of the terminal
|
||||
static WIDTH: Cell<usize> = const { Cell::new(DEFAULT_COLUMN_WIDTH) };
|
||||
|
||||
}
|
||||
|
||||
/// Print to terminal output to a buffer
|
||||
pub(crate) fn entrypoint(stream: &MdStream<'_>, buf: &mut Vec<u8>) -> io::Result<()> {
|
||||
#[cfg(not(test))]
|
||||
if let Some((w, _)) = termize::dimensions() {
|
||||
WIDTH.set(std::cmp::min(w, DEFAULT_COLUMN_WIDTH));
|
||||
}
|
||||
write_stream(stream, buf, None, 0)?;
|
||||
/// Print to the terminal output to a buffer
|
||||
/// optionally with a formatter for code blocks
|
||||
pub(crate) fn entrypoint(
|
||||
stream: &MdStream<'_>,
|
||||
buf: &mut Vec<u8>,
|
||||
formatter: Option<&(dyn Fn(&str, &mut Vec<u8>) -> io::Result<()> + 'static)>,
|
||||
) -> io::Result<()> {
|
||||
write_stream(stream, buf, None, 0, formatter)?;
|
||||
buf.write_all(b"\n")
|
||||
}
|
||||
/// Write the buffer, reset to the default style after each
|
||||
|
||||
/// Write the buffer, reset to the default style after each,
|
||||
/// optionally with a formatter for code blocks
|
||||
fn write_stream(
|
||||
MdStream(stream): &MdStream<'_>,
|
||||
buf: &mut Vec<u8>,
|
||||
|
||||
default: Option<Style>,
|
||||
indent: usize,
|
||||
formatter: Option<&(dyn Fn(&str, &mut Vec<u8>) -> io::Result<()> + 'static)>,
|
||||
) -> io::Result<()> {
|
||||
for tt in stream {
|
||||
write_tt(tt, buf, default, indent)?;
|
||||
write_tt(tt, buf, default, indent, formatter)?;
|
||||
}
|
||||
reset_opt_style(buf, default)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -43,12 +47,17 @@ fn write_tt(
|
|||
buf: &mut Vec<u8>,
|
||||
default: Option<Style>,
|
||||
indent: usize,
|
||||
formatter: Option<&(dyn Fn(&str, &mut Vec<u8>) -> io::Result<()> + 'static)>,
|
||||
) -> io::Result<()> {
|
||||
match tt {
|
||||
MdTree::CodeBlock { txt, lang: _ } => {
|
||||
reset_opt_style(buf, default)?;
|
||||
let style = Style::new().effects(Effects::DIMMED);
|
||||
write!(buf, "{style}{txt}{style:#}")?;
|
||||
if let Some(formatter) = formatter {
|
||||
formatter(txt, buf)?;
|
||||
} else {
|
||||
let style = Style::new().effects(Effects::DIMMED);
|
||||
write!(buf, "{style}{txt}{style:#}")?;
|
||||
}
|
||||
render_opt_style(buf, default)?;
|
||||
}
|
||||
MdTree::CodeInline(txt) => {
|
||||
|
|
@ -105,7 +114,7 @@ fn write_tt(
|
|||
};
|
||||
reset_opt_style(buf, default)?;
|
||||
write!(buf, "{cs}")?;
|
||||
write_stream(stream, buf, Some(cs), 0)?;
|
||||
write_stream(stream, buf, Some(cs), 0, None)?;
|
||||
write!(buf, "{cs:#}")?;
|
||||
render_opt_style(buf, default)?;
|
||||
buf.write_all(b"\n")?;
|
||||
|
|
@ -113,12 +122,12 @@ fn write_tt(
|
|||
MdTree::OrderedListItem(n, stream) => {
|
||||
let base = format!("{n}. ");
|
||||
write_wrapping(buf, &format!("{base:<4}"), indent, None, None)?;
|
||||
write_stream(stream, buf, None, indent + 4)?;
|
||||
write_stream(stream, buf, None, indent + 4, None)?;
|
||||
}
|
||||
MdTree::UnorderedListItem(stream) => {
|
||||
let base = "* ";
|
||||
write_wrapping(buf, &format!("{base:<4}"), indent, None, None)?;
|
||||
write_stream(stream, buf, None, indent + 4)?;
|
||||
write_stream(stream, buf, None, indent + 4, None)?;
|
||||
}
|
||||
// Patterns popped in previous step
|
||||
MdTree::Comment(_) | MdTree::LinkDef { .. } | MdTree::RefLink { .. } => unreachable!(),
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
[1m[4m[96mH1 Heading ]8;;http://docs.rs\with a link]8;;\[0m[0m
|
||||
[1m[4m[96mH1 Heading ]8;;http://docs.rs\with a link]8;;\[0m
|
||||
H1 content: [1msome words in bold[0m and [2mso does inline code[0m
|
||||
|
||||
[4m[96mH2 Heading[0m[0m
|
||||
[4m[96mH2 Heading[0m
|
||||
H2 content: [3msome words in italic[0m
|
||||
|
||||
[3m[96mH3 Heading[0m[0m
|
||||
[3m[96mH3 Heading[0m
|
||||
H3 content: [9mstrikethrough[0m text
|
||||
|
||||
[3m[4m[36mH4 Heading[0m[0m
|
||||
[3m[4m[36mH4 Heading[0m
|
||||
H4 content: A ]8;;https://docs.rs\simple link]8;;\ and a ]8;;http://docs.rs\remote-link]8;;\.
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------
|
||||
A section break was above. We can also do paragraph breaks:
|
||||
|
|
@ -24,7 +24,7 @@ Or ordered:
|
|||
elit quam, pulvinar ac risus in, dictum vehicula turpis. Vestibulum neque est, accumsan in cursus sit amet, dictum a nunc. Suspendisse
|
||||
aliquet, lorem eu eleifend accumsan, magna neque sodales nisi, a aliquet lectus leo eu sem.
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------
|
||||
[4m[96mCode[0m[0m
|
||||
[4m[96mCode[0m
|
||||
Both [2minline code[0m and code blocks are supported:
|
||||
|
||||
[2m/// A rust enum
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ fn test_output() {
|
|||
let bless = std::env::var_os("RUSTC_BLESS").is_some_and(|v| v != "0");
|
||||
let ast = MdStream::parse_str(INPUT);
|
||||
let mut buffer = Vec::new();
|
||||
ast.write_anstream_buf(&mut buffer).unwrap();
|
||||
ast.write_anstream_buf(&mut buffer, None).unwrap();
|
||||
|
||||
let mut blessed = PathBuf::new();
|
||||
blessed.extend(OUTPUT_PATH);
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ impl Translator {
|
|||
) -> Result<Cow<'a, str>, TranslateError<'a>> {
|
||||
trace!(?message, ?args);
|
||||
let (identifier, attr) = match message {
|
||||
DiagMessage::Str(msg) | DiagMessage::Translated(msg) => {
|
||||
DiagMessage::Str(msg) => {
|
||||
return Ok(Cow::Borrowed(msg));
|
||||
}
|
||||
DiagMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ rustc_hir = { path = "../rustc_hir" }
|
|||
rustc_lexer = { path = "../rustc_lexer" }
|
||||
rustc_lint_defs = { path = "../rustc_lint_defs" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_middle = { path = "../rustc_middle" }
|
||||
rustc_parse = { path = "../rustc_parse" }
|
||||
# We must use the proc_macro version that we will compile proc-macros against,
|
||||
# not the one from our own sysroot.
|
||||
|
|
@ -28,6 +29,7 @@ rustc_proc_macro = { path = "../rustc_proc_macro" }
|
|||
rustc_serialize = { path = "../rustc_serialize" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
scoped-tls = "1.0"
|
||||
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
|
||||
thin-vec = "0.2.12"
|
||||
tracing = "0.1"
|
||||
|
|
|
|||
|
|
@ -1173,6 +1173,10 @@ pub trait ResolverExpand {
|
|||
/// Record the name of an opaque `Ty::ImplTrait` pre-expansion so that it can be used
|
||||
/// to generate an item name later that does not reference placeholder macros.
|
||||
fn insert_impl_trait_name(&mut self, id: NodeId, name: Symbol);
|
||||
|
||||
/// Mark the scope as having a compile error so that error for lookup in this scope
|
||||
/// should be suppressed
|
||||
fn mark_scope_with_compile_error(&mut self, parent_node: NodeId);
|
||||
}
|
||||
|
||||
pub trait LintStoreExpand {
|
||||
|
|
@ -1351,8 +1355,6 @@ impl<'a> ExtCtxt<'a> {
|
|||
for (span, notes) in self.expansions.iter() {
|
||||
let mut db = self.dcx().create_note(errors::TraceMacro { span: *span });
|
||||
for note in notes {
|
||||
// FIXME: make this translatable
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
db.note(note.clone());
|
||||
}
|
||||
db.emit();
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ use rustc_feature::{
|
|||
ACCEPTED_LANG_FEATURES, EnabledLangFeature, EnabledLibFeature, Features, REMOVED_LANG_FEATURES,
|
||||
UNSTABLE_LANG_FEATURES,
|
||||
};
|
||||
use rustc_hir::Target;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::{STDLIB_STABLE_CRATES, Span, Symbol, sym};
|
||||
|
|
@ -403,6 +404,8 @@ impl<'a> StripUnconfigured<'a> {
|
|||
attr,
|
||||
attr.span,
|
||||
self.lint_node_id,
|
||||
// Doesn't matter what the target actually is here.
|
||||
Target::Crate,
|
||||
self.features,
|
||||
emit_errors,
|
||||
parse_cfg,
|
||||
|
|
|
|||
|
|
@ -999,7 +999,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
})
|
||||
}
|
||||
|
||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||
fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
|
||||
let kind = match item {
|
||||
Annotatable::Item(_)
|
||||
|
|
@ -2218,6 +2217,8 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
|||
&attr,
|
||||
attr.span,
|
||||
self.cfg().lint_node_id,
|
||||
// Target doesn't matter for `cfg` parsing.
|
||||
Target::Crate,
|
||||
self.cfg().features,
|
||||
ShouldEmit::ErrorsAndLints,
|
||||
parse_cfg,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||
#![cfg_attr(bootstrap, feature(array_windows))]
|
||||
#![feature(associated_type_defaults)]
|
||||
#![feature(if_let_guard)]
|
||||
|
|
@ -13,8 +12,6 @@
|
|||
|
||||
mod build;
|
||||
mod errors;
|
||||
// FIXME(Nilstrieb) Translate macro_rules diagnostics
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
mod mbe;
|
||||
mod placeholders;
|
||||
mod proc_macro_server;
|
||||
|
|
@ -25,8 +22,10 @@ pub mod base;
|
|||
pub mod config;
|
||||
pub mod expand;
|
||||
pub mod module;
|
||||
// FIXME(Nilstrieb) Translate proc_macro diagnostics
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
pub mod proc_macro;
|
||||
|
||||
pub fn provide(providers: &mut rustc_middle::query::Providers) {
|
||||
providers.derive_macro_expansion = proc_macro::provide_derive_macro_expansion;
|
||||
}
|
||||
|
||||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_parse::parser::{ForceCollect, Parser};
|
||||
use rustc_session::Session;
|
||||
use rustc_session::config::ProcMacroExecutionStrategy;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::profiling::SpannedEventArgRecorder;
|
||||
use rustc_span::{LocalExpnId, Span};
|
||||
use {rustc_ast as ast, rustc_proc_macro as pm};
|
||||
|
||||
use crate::base::{self, *};
|
||||
|
|
@ -30,9 +32,9 @@ impl<T> pm::bridge::server::MessagePipe<T> for MessagePipe<T> {
|
|||
}
|
||||
}
|
||||
|
||||
fn exec_strategy(ecx: &ExtCtxt<'_>) -> impl pm::bridge::server::ExecutionStrategy + 'static {
|
||||
fn exec_strategy(sess: &Session) -> impl pm::bridge::server::ExecutionStrategy + 'static {
|
||||
pm::bridge::server::MaybeCrossThread::<MessagePipe<_>>::new(
|
||||
ecx.sess.opts.unstable_opts.proc_macro_execution_strategy
|
||||
sess.opts.unstable_opts.proc_macro_execution_strategy
|
||||
== ProcMacroExecutionStrategy::CrossThread,
|
||||
)
|
||||
}
|
||||
|
|
@ -54,7 +56,7 @@ impl base::BangProcMacro for BangProcMacro {
|
|||
});
|
||||
|
||||
let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
|
||||
let strategy = exec_strategy(ecx);
|
||||
let strategy = exec_strategy(ecx.sess);
|
||||
let server = proc_macro_server::Rustc::new(ecx);
|
||||
self.client.run(&strategy, server, input, proc_macro_backtrace).map_err(|e| {
|
||||
ecx.dcx().emit_err(errors::ProcMacroPanicked {
|
||||
|
|
@ -85,7 +87,7 @@ impl base::AttrProcMacro for AttrProcMacro {
|
|||
});
|
||||
|
||||
let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
|
||||
let strategy = exec_strategy(ecx);
|
||||
let strategy = exec_strategy(ecx.sess);
|
||||
let server = proc_macro_server::Rustc::new(ecx);
|
||||
self.client.run(&strategy, server, annotation, annotated, proc_macro_backtrace).map_err(
|
||||
|e| {
|
||||
|
|
@ -101,7 +103,7 @@ impl base::AttrProcMacro for AttrProcMacro {
|
|||
}
|
||||
|
||||
pub struct DeriveProcMacro {
|
||||
pub client: pm::bridge::client::Client<pm::TokenStream, pm::TokenStream>,
|
||||
pub client: DeriveClient,
|
||||
}
|
||||
|
||||
impl MultiItemModifier for DeriveProcMacro {
|
||||
|
|
@ -113,6 +115,13 @@ impl MultiItemModifier for DeriveProcMacro {
|
|||
item: Annotatable,
|
||||
_is_derive_const: bool,
|
||||
) -> ExpandResult<Vec<Annotatable>, Annotatable> {
|
||||
let _timer = ecx.sess.prof.generic_activity_with_arg_recorder(
|
||||
"expand_derive_proc_macro_outer",
|
||||
|recorder| {
|
||||
recorder.record_arg_with_span(ecx.sess.source_map(), ecx.expansion_descr(), span);
|
||||
},
|
||||
);
|
||||
|
||||
// We need special handling for statement items
|
||||
// (e.g. `fn foo() { #[derive(Debug)] struct Bar; }`)
|
||||
let is_stmt = matches!(item, Annotatable::Stmt(..));
|
||||
|
|
@ -123,36 +132,31 @@ impl MultiItemModifier for DeriveProcMacro {
|
|||
// altogether. See #73345.
|
||||
crate::base::ann_pretty_printing_compatibility_hack(&item, &ecx.sess.psess);
|
||||
let input = item.to_tokens();
|
||||
let stream = {
|
||||
let _timer =
|
||||
ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| {
|
||||
recorder.record_arg_with_span(
|
||||
ecx.sess.source_map(),
|
||||
ecx.expansion_descr(),
|
||||
span,
|
||||
);
|
||||
});
|
||||
let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
|
||||
let strategy = exec_strategy(ecx);
|
||||
let server = proc_macro_server::Rustc::new(ecx);
|
||||
match self.client.run(&strategy, server, input, proc_macro_backtrace) {
|
||||
Ok(stream) => stream,
|
||||
Err(e) => {
|
||||
ecx.dcx().emit_err({
|
||||
errors::ProcMacroDerivePanicked {
|
||||
span,
|
||||
message: e.as_str().map(|message| {
|
||||
errors::ProcMacroDerivePanickedHelp { message: message.into() }
|
||||
}),
|
||||
}
|
||||
});
|
||||
return ExpandResult::Ready(vec![]);
|
||||
}
|
||||
}
|
||||
|
||||
let invoc_id = ecx.current_expansion.id;
|
||||
|
||||
let res = if ecx.sess.opts.incremental.is_some()
|
||||
&& ecx.sess.opts.unstable_opts.cache_proc_macros
|
||||
{
|
||||
ty::tls::with(|tcx| {
|
||||
let input = &*tcx.arena.alloc(input);
|
||||
let key: (LocalExpnId, &TokenStream) = (invoc_id, input);
|
||||
|
||||
QueryDeriveExpandCtx::enter(ecx, self.client, move || {
|
||||
tcx.derive_macro_expansion(key).cloned()
|
||||
})
|
||||
})
|
||||
} else {
|
||||
expand_derive_macro(invoc_id, input, ecx, self.client)
|
||||
};
|
||||
|
||||
let Ok(output) = res else {
|
||||
// error will already have been emitted
|
||||
return ExpandResult::Ready(vec![]);
|
||||
};
|
||||
|
||||
let error_count_before = ecx.dcx().err_count();
|
||||
let mut parser = Parser::new(&ecx.sess.psess, stream, Some("proc-macro derive"));
|
||||
let mut parser = Parser::new(&ecx.sess.psess, output, Some("proc-macro derive"));
|
||||
let mut items = vec![];
|
||||
|
||||
loop {
|
||||
|
|
@ -180,3 +184,101 @@ impl MultiItemModifier for DeriveProcMacro {
|
|||
ExpandResult::Ready(items)
|
||||
}
|
||||
}
|
||||
|
||||
/// Provide a query for computing the output of a derive macro.
|
||||
pub(super) fn provide_derive_macro_expansion<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
key: (LocalExpnId, &'tcx TokenStream),
|
||||
) -> Result<&'tcx TokenStream, ()> {
|
||||
let (invoc_id, input) = key;
|
||||
|
||||
// Make sure that we invalidate the query when the crate defining the proc macro changes
|
||||
let _ = tcx.crate_hash(invoc_id.expn_data().macro_def_id.unwrap().krate);
|
||||
|
||||
QueryDeriveExpandCtx::with(|ecx, client| {
|
||||
expand_derive_macro(invoc_id, input.clone(), ecx, client).map(|ts| &*tcx.arena.alloc(ts))
|
||||
})
|
||||
}
|
||||
|
||||
type DeriveClient = pm::bridge::client::Client<pm::TokenStream, pm::TokenStream>;
|
||||
|
||||
fn expand_derive_macro(
|
||||
invoc_id: LocalExpnId,
|
||||
input: TokenStream,
|
||||
ecx: &mut ExtCtxt<'_>,
|
||||
client: DeriveClient,
|
||||
) -> Result<TokenStream, ()> {
|
||||
let _timer =
|
||||
ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| {
|
||||
let invoc_expn_data = invoc_id.expn_data();
|
||||
let span = invoc_expn_data.call_site;
|
||||
let event_arg = invoc_expn_data.kind.descr();
|
||||
recorder.record_arg_with_span(ecx.sess.source_map(), event_arg.clone(), span);
|
||||
});
|
||||
|
||||
let proc_macro_backtrace = ecx.ecfg.proc_macro_backtrace;
|
||||
let strategy = exec_strategy(ecx.sess);
|
||||
let server = proc_macro_server::Rustc::new(ecx);
|
||||
|
||||
match client.run(&strategy, server, input, proc_macro_backtrace) {
|
||||
Ok(stream) => Ok(stream),
|
||||
Err(e) => {
|
||||
let invoc_expn_data = invoc_id.expn_data();
|
||||
let span = invoc_expn_data.call_site;
|
||||
ecx.dcx().emit_err({
|
||||
errors::ProcMacroDerivePanicked {
|
||||
span,
|
||||
message: e.as_str().map(|message| errors::ProcMacroDerivePanickedHelp {
|
||||
message: message.into(),
|
||||
}),
|
||||
}
|
||||
});
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Stores the context necessary to expand a derive proc macro via a query.
|
||||
struct QueryDeriveExpandCtx {
|
||||
/// Type-erased version of `&mut ExtCtxt`
|
||||
expansion_ctx: *mut (),
|
||||
client: DeriveClient,
|
||||
}
|
||||
|
||||
impl QueryDeriveExpandCtx {
|
||||
/// Store the extension context and the client into the thread local value.
|
||||
/// It will be accessible via the `with` method while `f` is active.
|
||||
fn enter<F, R>(ecx: &mut ExtCtxt<'_>, client: DeriveClient, f: F) -> R
|
||||
where
|
||||
F: FnOnce() -> R,
|
||||
{
|
||||
// We need erasure to get rid of the lifetime
|
||||
let ctx = Self { expansion_ctx: ecx as *mut _ as *mut (), client };
|
||||
DERIVE_EXPAND_CTX.set(&ctx, || f())
|
||||
}
|
||||
|
||||
/// Accesses the thread local value of the derive expansion context.
|
||||
/// Must be called while the `enter` function is active.
|
||||
fn with<F, R>(f: F) -> R
|
||||
where
|
||||
F: for<'a, 'b> FnOnce(&'b mut ExtCtxt<'a>, DeriveClient) -> R,
|
||||
{
|
||||
DERIVE_EXPAND_CTX.with(|ctx| {
|
||||
let ectx = {
|
||||
let casted = ctx.expansion_ctx.cast::<ExtCtxt<'_>>();
|
||||
// SAFETY: We can only get the value from `with` while the `enter` function
|
||||
// is active (on the callstack), and that function's signature ensures that the
|
||||
// lifetime is valid.
|
||||
// If `with` is called at some other time, it will panic due to usage of
|
||||
// `scoped_tls::with`.
|
||||
unsafe { casted.as_mut().unwrap() }
|
||||
};
|
||||
|
||||
f(ectx, ctx.client)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// When we invoke a query to expand a derive proc macro, we need to provide it with the expansion
|
||||
// context and derive Client. We do that using a thread-local.
|
||||
scoped_tls::scoped_thread_local!(static DERIVE_EXPAND_CTX: QueryDeriveExpandCtx);
|
||||
|
|
|
|||
|
|
@ -548,9 +548,6 @@ impl server::FreeFunctions for Rustc<'_, '_> {
|
|||
Diag::new(self.psess().dcx(), diagnostic.level.to_internal(), message);
|
||||
diag.span(MultiSpan::from_spans(diagnostic.spans));
|
||||
for child in diagnostic.children {
|
||||
// This message comes from another diagnostic, and we are just reconstructing the
|
||||
// diagnostic, so there's no need for translation.
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
diag.sub(child.level.to_internal(), child.message, MultiSpan::from_spans(child.spans));
|
||||
}
|
||||
diag.emit();
|
||||
|
|
|
|||
|
|
@ -678,7 +678,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
rustc_attr!(
|
||||
rustc_pass_indirectly_in_non_rustic_abis, Normal, template!(Word), ErrorFollowing,
|
||||
EncodeCrossCrate::No,
|
||||
"types marked with `#[rustc_pass_indirectly_in_non_rustic_abis]` are always passed indirectly by non-Rustic abis."
|
||||
"types marked with `#[rustc_pass_indirectly_in_non_rustic_abis]` are always passed indirectly by non-Rustic ABIs"
|
||||
),
|
||||
|
||||
// Limits:
|
||||
|
|
@ -1182,12 +1182,6 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
rustc_lint_untracked_query_information, Normal, template!(Word),
|
||||
WarnFollowing, EncodeCrossCrate::Yes,
|
||||
),
|
||||
// Used by the `rustc::diagnostic_outside_of_impl` lints to assist in changes to diagnostic
|
||||
// APIs. Any function with this attribute will be checked by that lint.
|
||||
rustc_attr!(
|
||||
rustc_lint_diagnostics, Normal, template!(Word),
|
||||
WarnFollowing, EncodeCrossCrate::Yes,
|
||||
),
|
||||
// Used by the `rustc::bad_opt_access` lint to identify `DebuggingOptions` and `CodegenOptions`
|
||||
// types (as well as any others in future).
|
||||
rustc_attr!(
|
||||
|
|
@ -1275,38 +1269,38 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
rustc_attr!(
|
||||
rustc_as_ptr, Normal, template!(Word), ErrorFollowing,
|
||||
EncodeCrossCrate::Yes,
|
||||
"`#[rustc_as_ptr]` is used to mark functions returning pointers to their inner allocations."
|
||||
"`#[rustc_as_ptr]` is used to mark functions returning pointers to their inner allocations"
|
||||
),
|
||||
rustc_attr!(
|
||||
rustc_should_not_be_called_on_const_items, Normal, template!(Word), ErrorFollowing,
|
||||
EncodeCrossCrate::Yes,
|
||||
"`#[rustc_should_not_be_called_on_const_items]` is used to mark methods that don't make sense to be called on interior mutable consts."
|
||||
"`#[rustc_should_not_be_called_on_const_items]` is used to mark methods that don't make sense to be called on interior mutable consts"
|
||||
),
|
||||
rustc_attr!(
|
||||
rustc_pass_by_value, Normal, template!(Word), ErrorFollowing,
|
||||
EncodeCrossCrate::Yes,
|
||||
"`#[rustc_pass_by_value]` is used to mark types that must be passed by value instead of reference."
|
||||
"`#[rustc_pass_by_value]` is used to mark types that must be passed by value instead of reference"
|
||||
),
|
||||
rustc_attr!(
|
||||
rustc_never_returns_null_ptr, Normal, template!(Word), ErrorFollowing,
|
||||
EncodeCrossCrate::Yes,
|
||||
"`#[rustc_never_returns_null_ptr]` is used to mark functions returning non-null pointers."
|
||||
"`#[rustc_never_returns_null_ptr]` is used to mark functions returning non-null pointers"
|
||||
),
|
||||
rustc_attr!(
|
||||
rustc_no_implicit_autorefs, AttributeType::Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes,
|
||||
"`#[rustc_no_implicit_autorefs]` is used to mark functions for which an autoref to the dereference of a raw pointer should not be used as an argument."
|
||||
"`#[rustc_no_implicit_autorefs]` is used to mark functions for which an autoref to the dereference of a raw pointer should not be used as an argument"
|
||||
),
|
||||
rustc_attr!(
|
||||
rustc_coherence_is_core, AttributeType::CrateLevel, template!(Word), ErrorFollowing, EncodeCrossCrate::No,
|
||||
"`#![rustc_coherence_is_core]` allows inherent methods on builtin types, only intended to be used in `core`."
|
||||
"`#![rustc_coherence_is_core]` allows inherent methods on builtin types, only intended to be used in `core`"
|
||||
),
|
||||
rustc_attr!(
|
||||
rustc_coinductive, AttributeType::Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No,
|
||||
"`#[rustc_coinductive]` changes a trait to be coinductive, allowing cycles in the trait solver."
|
||||
"`#[rustc_coinductive]` changes a trait to be coinductive, allowing cycles in the trait solver"
|
||||
),
|
||||
rustc_attr!(
|
||||
rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::No,
|
||||
"`#[rustc_allow_incoherent_impl]` has to be added to all impl items of an incoherent inherent impl."
|
||||
"`#[rustc_allow_incoherent_impl]` has to be added to all impl items of an incoherent inherent impl"
|
||||
),
|
||||
rustc_attr!(
|
||||
rustc_preserve_ub_checks, AttributeType::CrateLevel, template!(Word), ErrorFollowing, EncodeCrossCrate::No,
|
||||
|
|
@ -1333,7 +1327,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
rustc_has_incoherent_inherent_impls, AttributeType::Normal, template!(Word),
|
||||
ErrorFollowing, EncodeCrossCrate::Yes,
|
||||
"`#[rustc_has_incoherent_inherent_impls]` allows the addition of incoherent inherent impls for \
|
||||
the given type by annotating all impl items with `#[rustc_allow_incoherent_impl]`."
|
||||
the given type by annotating all impl items with `#[rustc_allow_incoherent_impl]`"
|
||||
),
|
||||
|
||||
BuiltinAttribute {
|
||||
|
|
@ -1396,7 +1390,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
EncodeCrossCrate::No,
|
||||
"the `#[rustc_skip_during_method_dispatch]` attribute is used to exclude a trait \
|
||||
from method dispatch when the receiver is of the following type, for compatibility in \
|
||||
editions < 2021 (array) or editions < 2024 (boxed_slice)."
|
||||
editions < 2021 (array) or editions < 2024 (boxed_slice)"
|
||||
),
|
||||
rustc_attr!(
|
||||
rustc_must_implement_one_of, Normal, template!(List: &["function1, function2, ..."]),
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue