Merge ref '2cd4ee6bcf' from rust-lang/rust

Pull recent changes from https://github.com/rust-lang/rust via Josh.

Upstream ref: 2cd4ee6bcf
Filtered ref: 0fa640c05f720805b85aaf146087ed923ab5b9cb
Upstream diff: dc47a69ed9...2cd4ee6bcf

This merge was created using https://github.com/rust-lang/josh-sync.
This commit is contained in:
The Miri Cronjob Bot 2025-12-14 05:06:23 +00:00
commit 705ec58e00
179 changed files with 2249 additions and 1796 deletions

View file

@ -4630,7 +4630,6 @@ dependencies = [
name = "rustc_session"
version = "0.0.0"
dependencies = [
"bitflags",
"getopts",
"libc",
"rand 0.9.2",
@ -4657,6 +4656,7 @@ dependencies = [
name = "rustc_span"
version = "0.0.0"
dependencies = [
"bitflags",
"blake3",
"derive-where",
"indexmap",

View file

@ -1533,11 +1533,10 @@ impl Expr {
// then type of result is trait object.
// Otherwise we don't assume the result type.
ExprKind::Binary(binop, lhs, rhs) if binop.node == BinOpKind::Add => {
if let (Some(lhs), Some(rhs)) = (lhs.to_bound(), rhs.to_bound()) {
TyKind::TraitObject(vec![lhs, rhs], TraitObjectSyntax::None)
} else {
let (Some(lhs), Some(rhs)) = (lhs.to_bound(), rhs.to_bound()) else {
return None;
}
};
TyKind::TraitObject(vec![lhs, rhs], TraitObjectSyntax::None)
}
ExprKind::Underscore => TyKind::Infer,

View file

@ -447,20 +447,17 @@ impl MetaItem {
thin_vec![PathSegment::path_root(span)]
};
loop {
if let Some(&TokenTree::Token(Token { kind: token::Ident(name, _), span }, _)) =
let Some(&TokenTree::Token(Token { kind: token::Ident(name, _), span }, _)) =
iter.next().map(|tt| TokenTree::uninterpolate(tt)).as_deref()
{
segments.push(PathSegment::from_ident(Ident::new(name, span)));
} else {
else {
return None;
}
if let Some(TokenTree::Token(Token { kind: token::PathSep, .. }, _)) =
iter.peek()
{
iter.next();
} else {
};
segments.push(PathSegment::from_ident(Ident::new(name, span)));
let Some(TokenTree::Token(Token { kind: token::PathSep, .. }, _)) = iter.peek()
else {
break;
}
};
iter.next();
}
let span = span.with_hi(segments.last().unwrap().ident.span.hi());
Path { span, segments, tokens: None }

View file

@ -6,6 +6,7 @@
// tidy-alphabetical-start
#![cfg_attr(bootstrap, feature(array_windows))]
#![deny(clippy::manual_let_else)]
#![doc(test(attr(deny(warnings), allow(internal_features))))]
#![feature(associated_type_defaults)]
#![feature(box_patterns)]

View file

@ -43,13 +43,15 @@ use hir::def::{DefKind, PartialRes, Res};
use hir::{BodyId, HirId};
use rustc_abi::ExternAbi;
use rustc_ast::*;
use rustc_attr_parsing::{AttributeParser, ShouldEmit};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::Target;
use rustc_hir::attrs::{AttributeKind, InlineAttr};
use rustc_hir::def_id::DefId;
use rustc_middle::span_bug;
use rustc_middle::ty::{Asyncness, ResolverAstLowering};
use rustc_middle::ty::{Asyncness, DelegationFnSigAttrs, ResolverAstLowering};
use rustc_span::symbol::kw;
use rustc_span::{Ident, Span, Symbol};
use rustc_span::{DUMMY_SP, Ident, Span, Symbol};
use {rustc_ast as ast, rustc_hir as hir};
use super::{GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode};
@ -62,6 +64,41 @@ pub(crate) struct DelegationResults<'hir> {
pub generics: &'hir hir::Generics<'hir>,
}
struct AttributeAdditionInfo {
pub equals: fn(&hir::Attribute) -> bool,
pub kind: AttributeAdditionKind,
}
enum AttributeAdditionKind {
Default { factory: fn(Span) -> hir::Attribute },
Inherit { flag: DelegationFnSigAttrs, factory: fn(Span, &hir::Attribute) -> hir::Attribute },
}
const PARENT_ID: hir::ItemLocalId = hir::ItemLocalId::ZERO;
static ATTRIBUTES_ADDITIONS: &[AttributeAdditionInfo] = &[
AttributeAdditionInfo {
equals: |a| matches!(a, hir::Attribute::Parsed(AttributeKind::MustUse { .. })),
kind: AttributeAdditionKind::Inherit {
factory: |span, original_attribute| {
let reason = match original_attribute {
hir::Attribute::Parsed(AttributeKind::MustUse { reason, .. }) => *reason,
_ => None,
};
hir::Attribute::Parsed(AttributeKind::MustUse { span, reason })
},
flag: DelegationFnSigAttrs::MUST_USE,
},
},
AttributeAdditionInfo {
equals: |a| matches!(a, hir::Attribute::Parsed(AttributeKind::Inline(..))),
kind: AttributeAdditionKind::Default {
factory: |span| hir::Attribute::Parsed(AttributeKind::Inline(InlineAttr::Hint, span)),
},
},
];
impl<'hir> LoweringContext<'_, 'hir> {
fn is_method(&self, def_id: DefId, span: Span) -> bool {
match self.tcx.def_kind(def_id) {
@ -88,7 +125,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let sig_id = self.get_delegation_sig_id(item_id, delegation.id, span, is_in_trait_impl);
match sig_id {
Ok(sig_id) => {
self.add_inline_attribute_if_needed(span);
self.add_attributes_if_needed(span, sig_id);
let is_method = self.is_method(sig_id, span);
let (param_count, c_variadic) = self.param_count(sig_id);
@ -103,29 +140,100 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}
fn add_inline_attribute_if_needed(&mut self, span: Span) {
const PARENT_ID: hir::ItemLocalId = hir::ItemLocalId::ZERO;
let create_inline_attr_slice =
|| [hir::Attribute::Parsed(AttributeKind::Inline(InlineAttr::Hint, span))];
fn add_attributes_if_needed(&mut self, span: Span, sig_id: DefId) {
let new_attributes = self.create_new_attributes(
ATTRIBUTES_ADDITIONS,
span,
sig_id,
self.attrs.get(&PARENT_ID),
);
let new_attributes = match self.attrs.get(&PARENT_ID) {
Some(attrs) => {
// Check if reuse already specifies any inline attribute, if so, do nothing
if attrs
.iter()
.any(|a| matches!(a, hir::Attribute::Parsed(AttributeKind::Inline(..))))
{
return;
}
if new_attributes.is_empty() {
return;
}
self.arena.alloc_from_iter(
attrs.into_iter().map(|a| a.clone()).chain(create_inline_attr_slice()),
)
}
None => self.arena.alloc_from_iter(create_inline_attr_slice()),
let new_arena_allocated_attributes = match self.attrs.get(&PARENT_ID) {
Some(existing_attrs) => self.arena.alloc_from_iter(
existing_attrs.iter().map(|a| a.clone()).chain(new_attributes.into_iter()),
),
None => self.arena.alloc_from_iter(new_attributes.into_iter()),
};
self.attrs.insert(PARENT_ID, new_attributes);
self.attrs.insert(PARENT_ID, new_arena_allocated_attributes);
}
fn create_new_attributes(
&self,
candidate_additions: &[AttributeAdditionInfo],
span: Span,
sig_id: DefId,
existing_attrs: Option<&&[hir::Attribute]>,
) -> Vec<hir::Attribute> {
let local_original_attributes = self.parse_local_original_attributes(sig_id);
candidate_additions
.iter()
.filter_map(|addition_info| {
if let Some(existing_attrs) = existing_attrs
&& existing_attrs
.iter()
.any(|existing_attr| (addition_info.equals)(existing_attr))
{
return None;
}
match addition_info.kind {
AttributeAdditionKind::Default { factory } => Some(factory(span)),
AttributeAdditionKind::Inherit { flag, factory } => {
let original_attribute = match sig_id.as_local() {
Some(local_id) => self
.resolver
.delegation_fn_sigs
.get(&local_id)
.is_some_and(|sig| sig.attrs_flags.contains(flag))
.then(|| {
local_original_attributes
.as_ref()
.map(|attrs| {
attrs
.iter()
.find(|base_attr| (addition_info.equals)(base_attr))
})
.flatten()
})
.flatten(),
None => self
.tcx
.get_all_attrs(sig_id)
.iter()
.find(|base_attr| (addition_info.equals)(base_attr)),
};
original_attribute.map(|a| factory(span, a))
}
}
})
.collect::<Vec<_>>()
}
fn parse_local_original_attributes(&self, sig_id: DefId) -> Option<Vec<hir::Attribute>> {
if let Some(local_id) = sig_id.as_local()
&& let Some(info) = self.resolver.delegation_fn_sigs.get(&local_id)
&& !info.to_inherit_attrs.is_empty()
{
Some(AttributeParser::parse_limited_all(
self.tcx.sess,
info.to_inherit_attrs.as_slice(),
None,
Target::Fn,
DUMMY_SP,
DUMMY_NODE_ID,
Some(self.tcx.features()),
ShouldEmit::Nothing,
))
} else {
None
}
}
fn get_delegation_sig_id(
@ -220,7 +328,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
// We are not forwarding the attributes, as the delegation fn sigs are collected on the ast,
// and here we need the hir attributes.
let default_safety =
if sig.target_feature || self.tcx.def_kind(parent) == DefKind::ForeignMod {
if sig.attrs_flags.contains(DelegationFnSigAttrs::TARGET_FEATURE)
|| self.tcx.def_kind(parent) == DefKind::ForeignMod
{
hir::Safety::Unsafe
} else {
hir::Safety::Safe

View file

@ -6,9 +6,6 @@ attr_parsing_bundle_needs_static =
attr_parsing_cfg_attr_bad_delim = wrong `cfg_attr` delimiters
attr_parsing_cfg_predicate_identifier =
`cfg` predicate key must be an identifier
attr_parsing_deprecated_item_suggestion =
suggestions on deprecated items are unstable
.help = add `#![feature(deprecated_suggestion)]` to the crate root
@ -41,9 +38,6 @@ attr_parsing_empty_link_name =
link name must not be empty
.label = empty link name
attr_parsing_expected_one_cfg_pattern =
expected 1 cfg-pattern
attr_parsing_expected_single_version_literal =
expected single version literal
@ -241,12 +235,6 @@ attr_parsing_unstable_cfg_target_compact =
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]`
attr_parsing_unsupported_literal_cfg_boolean =
literal in `cfg` predicate value must be a boolean
attr_parsing_unsupported_literal_cfg_string =
literal in `cfg` predicate value must be a string
attr_parsing_unsupported_literal_generic =
unsupported literal
attr_parsing_unsupported_literal_suggestion =
consider removing the prefix

View file

@ -4,7 +4,9 @@ use rustc_ast::token::Delimiter;
use rustc_ast::tokenstream::DelimSpan;
use rustc_ast::{AttrItem, Attribute, CRATE_NODE_ID, LitKind, ast, token};
use rustc_errors::{Applicability, PResult};
use rustc_feature::{AttrSuggestionStyle, AttributeTemplate, Features, template};
use rustc_feature::{
AttrSuggestionStyle, AttributeTemplate, Features, GatedCfg, find_gated_cfg, template,
};
use rustc_hir::attrs::CfgEntry;
use rustc_hir::lints::AttributeLintKind;
use rustc_hir::{AttrPath, RustcVersion};
@ -23,7 +25,7 @@ use crate::session_diagnostics::{
AttributeParseError, AttributeParseErrorReason, CfgAttrBadDelim, MetaBadDelimSugg,
ParsedDescription,
};
use crate::{AttributeParser, fluent_generated, parse_version, session_diagnostics, try_gate_cfg};
use crate::{AttributeParser, fluent_generated, parse_version, session_diagnostics};
pub const CFG_TEMPLATE: AttributeTemplate = template!(
List: &["predicate"],
@ -410,3 +412,19 @@ fn parse_cfg_attr_internal<'a>(
Ok((cfg_predicate, expanded_attrs))
}
fn try_gate_cfg(name: Symbol, span: Span, sess: &Session, features: Option<&Features>) {
let gate = find_gated_cfg(|sym| sym == name);
if let (Some(feats), Some(gated_cfg)) = (features, gate) {
gate_cfg(gated_cfg, span, sess, feats);
}
}
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &Session, features: &Features) {
let (cfg, feature, has_feature) = gated_cfg;
if !has_feature(features) && !cfg_span.allows_unstable(*feature) {
let explain = format!("`cfg({cfg})` is experimental and subject to change");
feature_err(sess, *feature, cfg_span, explain).emit();
}
}

View file

@ -1,210 +0,0 @@
use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, NodeId};
use rustc_ast_pretty::pprust;
use rustc_feature::{Features, GatedCfg, find_gated_cfg};
use rustc_hir::RustcVersion;
use rustc_session::Session;
use rustc_session::lint::{BuiltinLintDiag, Lint};
use rustc_session::parse::feature_err;
use rustc_span::{Span, Symbol, sym};
use crate::session_diagnostics::{self, UnsupportedLiteralReason};
use crate::{fluent_generated, parse_version};
/// Emitter of a builtin lint from `cfg_matches`.
///
/// Used to support emitting a lint (currently on check-cfg), either:
/// - as an early buffered lint (in `rustc`)
/// - or has a "normal" lint from HIR (in `rustdoc`)
pub trait CfgMatchesLintEmitter {
fn emit_span_lint(&self, sess: &Session, lint: &'static Lint, sp: Span, diag: BuiltinLintDiag);
}
impl CfgMatchesLintEmitter for NodeId {
fn emit_span_lint(&self, sess: &Session, lint: &'static Lint, sp: Span, diag: BuiltinLintDiag) {
sess.psess.buffer_lint(lint, sp, *self, diag);
}
}
#[derive(Clone, Debug)]
pub struct Condition {
pub name: Symbol,
pub name_span: Span,
pub value: Option<Symbol>,
pub value_span: Option<Span>,
pub span: Span,
}
pub fn try_gate_cfg(name: Symbol, span: Span, sess: &Session, features: Option<&Features>) {
let gate = find_gated_cfg(|sym| sym == name);
if let (Some(feats), Some(gated_cfg)) = (features, gate) {
gate_cfg(gated_cfg, span, sess, feats);
}
}
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &Session, features: &Features) {
let (cfg, feature, has_feature) = gated_cfg;
if !has_feature(features) && !cfg_span.allows_unstable(*feature) {
let explain = format!("`cfg({cfg})` is experimental and subject to change");
feature_err(sess, *feature, cfg_span, explain).emit();
}
}
/// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to
/// evaluate individual items.
pub fn eval_condition(
cfg: &MetaItemInner,
sess: &Session,
features: Option<&Features>,
eval: &mut impl FnMut(Condition) -> bool,
) -> bool {
let dcx = sess.dcx();
let cfg = match cfg {
MetaItemInner::MetaItem(meta_item) => meta_item,
MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => {
return *b;
}
_ => {
dcx.emit_err(session_diagnostics::UnsupportedLiteral {
span: cfg.span(),
reason: UnsupportedLiteralReason::CfgBoolean,
is_bytestr: false,
start_point_span: sess.source_map().start_point(cfg.span()),
});
return false;
}
};
match &cfg.kind {
MetaItemKind::List(mis) if cfg.has_name(sym::version) => {
try_gate_cfg(sym::version, cfg.span, sess, features);
let (min_version, span) = match &mis[..] {
[MetaItemInner::Lit(MetaItemLit { kind: LitKind::Str(sym, ..), span, .. })] => {
(sym, span)
}
[
MetaItemInner::Lit(MetaItemLit { span, .. })
| MetaItemInner::MetaItem(MetaItem { span, .. }),
] => {
dcx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: *span });
return false;
}
[..] => {
dcx.emit_err(session_diagnostics::ExpectedSingleVersionLiteral {
span: cfg.span,
});
return false;
}
};
let Some(min_version) = parse_version(*min_version) else {
dcx.emit_warn(session_diagnostics::UnknownVersionLiteral { span: *span });
return false;
};
// See https://github.com/rust-lang/rust/issues/64796#issuecomment-640851454 for details
if sess.psess.assume_incomplete_release {
RustcVersion::current_overridable() > min_version
} else {
RustcVersion::current_overridable() >= min_version
}
}
MetaItemKind::List(mis) => {
for mi in mis.iter() {
if mi.meta_item_or_bool().is_none() {
dcx.emit_err(session_diagnostics::UnsupportedLiteral {
span: mi.span(),
reason: UnsupportedLiteralReason::Generic,
is_bytestr: false,
start_point_span: sess.source_map().start_point(mi.span()),
});
return false;
}
}
// The unwraps below may look dangerous, but we've already asserted
// that they won't fail with the loop above.
match cfg.name() {
Some(sym::any) => mis
.iter()
// We don't use any() here, because we want to evaluate all cfg condition
// as eval_condition can (and does) extra checks
.fold(false, |res, mi| res | eval_condition(mi, sess, features, eval)),
Some(sym::all) => mis
.iter()
// We don't use all() here, because we want to evaluate all cfg condition
// as eval_condition can (and does) extra checks
.fold(true, |res, mi| res & eval_condition(mi, sess, features, eval)),
Some(sym::not) => {
let [mi] = mis.as_slice() else {
dcx.emit_err(session_diagnostics::ExpectedOneCfgPattern { span: cfg.span });
return false;
};
!eval_condition(mi, sess, features, eval)
}
Some(sym::target) => {
if let Some(features) = features
&& !features.cfg_target_compact()
{
feature_err(
sess,
sym::cfg_target_compact,
cfg.span,
fluent_generated::attr_parsing_unstable_cfg_target_compact,
)
.emit();
}
mis.iter().fold(true, |res, mi| {
let Some(mut mi) = mi.meta_item().cloned() else {
dcx.emit_err(session_diagnostics::CfgPredicateIdentifier {
span: mi.span(),
});
return false;
};
if let [seg, ..] = &mut mi.path.segments[..] {
seg.ident.name = Symbol::intern(&format!("target_{}", seg.ident.name));
}
res & eval_condition(&MetaItemInner::MetaItem(mi), sess, features, eval)
})
}
_ => {
dcx.emit_err(session_diagnostics::InvalidPredicate {
span: cfg.span,
predicate: pprust::path_to_string(&cfg.path),
});
false
}
}
}
MetaItemKind::Word | MetaItemKind::NameValue(..)
if cfg.path.segments.len() != 1
|| cfg.path.segments[0].ident.is_path_segment_keyword() =>
{
dcx.emit_err(session_diagnostics::CfgPredicateIdentifier { span: cfg.path.span });
true
}
MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
dcx.emit_err(session_diagnostics::UnsupportedLiteral {
span: lit.span,
reason: UnsupportedLiteralReason::CfgString,
is_bytestr: lit.kind.is_bytestr(),
start_point_span: sess.source_map().start_point(lit.span),
});
true
}
MetaItemKind::Word | MetaItemKind::NameValue(..) => {
let ident = cfg.ident().expect("multi-segment cfg predicate");
eval(Condition {
name: ident.name,
name_span: ident.span,
value: cfg.value_str(),
value_span: cfg.name_value_literal_span(),
span: cfg.span,
})
}
}
}

View file

@ -32,7 +32,6 @@ mod prelude;
pub(crate) mod allow_unstable;
pub(crate) mod body;
pub(crate) mod cfg;
pub(crate) mod cfg_old;
pub(crate) mod cfg_select;
pub(crate) mod codegen_attrs;
pub(crate) mod confusables;

View file

@ -8,7 +8,7 @@ use rustc_hir::{
use super::prelude::*;
use super::util::parse_version;
use crate::session_diagnostics::{self, UnsupportedLiteralReason};
use crate::session_diagnostics::{self};
macro_rules! reject_outside_std {
($cx: ident) => {
@ -302,12 +302,7 @@ pub(crate) fn parse_stability<S: Stage>(
for param in list.mixed() {
let param_span = param.span();
let Some(param) = param.meta_item() else {
cx.emit_err(session_diagnostics::UnsupportedLiteral {
span: param_span,
reason: UnsupportedLiteralReason::Generic,
is_bytestr: false,
start_point_span: cx.sess().source_map().start_point(param_span),
});
cx.unexpected_literal(param.span());
return None;
};
@ -382,12 +377,7 @@ pub(crate) fn parse_unstability<S: Stage>(
for param in list.mixed() {
let Some(param) = param.meta_item() else {
cx.emit_err(session_diagnostics::UnsupportedLiteral {
span: param.span(),
reason: UnsupportedLiteralReason::Generic,
is_bytestr: false,
start_point_span: cx.sess().source_map().start_point(param.span()),
});
cx.unexpected_literal(param.span());
return None;
};

View file

@ -107,7 +107,6 @@ pub mod validate_attr;
pub use attributes::cfg::{
CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg, parse_cfg_attr, parse_cfg_entry,
};
pub use attributes::cfg_old::*;
pub use attributes::cfg_select::*;
pub use attributes::util::{is_builtin_attr, parse_version};
pub use context::{Early, Late, OmitDoc, ShouldEmit};

View file

@ -12,19 +12,6 @@ use rustc_span::{Span, Symbol};
use crate::fluent_generated as fluent;
pub(crate) enum UnsupportedLiteralReason {
Generic,
CfgString,
CfgBoolean,
}
#[derive(Diagnostic)]
#[diag(attr_parsing_expected_one_cfg_pattern, code = E0536)]
pub(crate) struct ExpectedOneCfgPattern {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(attr_parsing_invalid_predicate, code = E0537)]
pub(crate) struct InvalidPredicate {
@ -230,46 +217,6 @@ pub(crate) struct InvalidReprHintNoValue {
pub name: Symbol,
}
/// Error code: E0565
// FIXME(jdonszelmann): slowly phased out
pub(crate) struct UnsupportedLiteral {
pub span: Span,
pub reason: UnsupportedLiteralReason,
pub is_bytestr: bool,
pub start_point_span: Span,
}
impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for UnsupportedLiteral {
fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
let mut diag = Diag::new(
dcx,
level,
match self.reason {
UnsupportedLiteralReason::Generic => {
fluent::attr_parsing_unsupported_literal_generic
}
UnsupportedLiteralReason::CfgString => {
fluent::attr_parsing_unsupported_literal_cfg_string
}
UnsupportedLiteralReason::CfgBoolean => {
fluent::attr_parsing_unsupported_literal_cfg_boolean
}
},
);
diag.span(self.span);
diag.code(E0565);
if self.is_bytestr {
diag.span_suggestion(
self.start_point_span,
fluent::attr_parsing_unsupported_literal_suggestion,
"",
Applicability::MaybeIncorrect,
);
}
diag
}
}
#[derive(Diagnostic)]
#[diag(attr_parsing_invalid_repr_align_need_arg, code = E0589)]
pub(crate) struct InvalidReprAlignNeedArg {
@ -375,13 +322,6 @@ pub(crate) struct RustcAllowedUnstablePairing {
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(attr_parsing_cfg_predicate_identifier)]
pub(crate) struct CfgPredicateIdentifier {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(attr_parsing_deprecated_item_suggestion)]
pub(crate) struct DeprecatedItemSuggestion {

View file

@ -561,11 +561,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
VarDebugInfoContents::Place(ref p) => p == place,
_ => false,
});
let arg_name = if let Some(var_info) = var_info {
var_info.name
} else {
return;
};
let Some(var_info) = var_info else { return };
let arg_name = var_info.name;
struct MatchArgFinder {
expr_span: Span,
match_arg_span: Option<Span>,

View file

@ -850,16 +850,10 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
// will only ever have one item at any given time, but by using a vector, we can pop from
// it which simplifies the termination logic.
let mut queue = vec![location];
let mut target =
if let Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) = stmt {
if let Some(local) = place.as_local() {
local
} else {
return false;
}
} else {
return false;
};
let Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) = stmt else {
return false;
};
let Some(mut target) = place.as_local() else { return false };
debug!("was_captured_by_trait: target={:?} queue={:?}", target, queue);
while let Some(current_location) = queue.pop() {

View file

@ -1124,16 +1124,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
use self::UseSpans::*;
debug!("borrow_spans: use_span={:?} location={:?}", use_span, location);
let target = match self.body[location.block].statements.get(location.statement_index) {
Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) => {
if let Some(local) = place.as_local() {
local
} else {
return OtherUse(use_span);
}
}
_ => return OtherUse(use_span),
let Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) =
self.body[location.block].statements.get(location.statement_index)
else {
return OtherUse(use_span);
};
let Some(target) = place.as_local() else { return OtherUse(use_span) };
if self.body.local_kind(target) != LocalKind::Temp {
// operands are always temporaries.

View file

@ -142,12 +142,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
} else {
item_msg = access_place_desc;
let local_info = self.body.local_decls[local].local_info();
if let LocalInfo::StaticRef { def_id, .. } = *local_info {
let static_name = &self.infcx.tcx.item_name(def_id);
reason = format!(", as `{static_name}` is an immutable static item");
} else {
let LocalInfo::StaticRef { def_id, .. } = *local_info else {
bug!("is_ref_to_static return true, but not ref to static?");
}
};
let static_name = &self.infcx.tcx.item_name(def_id);
reason = format!(", as `{static_name}` is an immutable static item");
}
}
PlaceRef { local, projection: [proj_base @ .., ProjectionElem::Deref] } => {

View file

@ -847,11 +847,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let fn_returns = self.infcx.tcx.return_type_impl_or_dyn_traits(suitable_region.scope);
let param = if let Some(param) =
let Some(param) =
find_param_with_region(self.infcx.tcx, self.mir_def_id(), f, outlived_f)
{
param
} else {
else {
return;
};
@ -930,37 +928,27 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let tcx = self.infcx.tcx;
let instance = if let ConstraintCategory::CallArgument(Some(func_ty)) = category {
let (fn_did, args) = match func_ty.kind() {
ty::FnDef(fn_did, args) => (fn_did, args),
_ => return,
};
debug!(?fn_did, ?args);
let ConstraintCategory::CallArgument(Some(func_ty)) = category else { return };
let ty::FnDef(fn_did, args) = func_ty.kind() else { return };
debug!(?fn_did, ?args);
// Only suggest this on function calls, not closures
let ty = tcx.type_of(fn_did).instantiate_identity();
debug!("ty: {:?}, ty.kind: {:?}", ty, ty.kind());
if let ty::Closure(_, _) = ty.kind() {
return;
}
if let Ok(Some(instance)) = ty::Instance::try_resolve(
tcx,
self.infcx.typing_env(self.infcx.param_env),
*fn_did,
self.infcx.resolve_vars_if_possible(args),
) {
instance
} else {
return;
}
} else {
// Only suggest this on function calls, not closures
let ty = tcx.type_of(fn_did).instantiate_identity();
debug!("ty: {:?}, ty.kind: {:?}", ty, ty.kind());
if let ty::Closure(_, _) = ty.kind() {
return;
}
let Ok(Some(instance)) = ty::Instance::try_resolve(
tcx,
self.infcx.typing_env(self.infcx.param_env),
*fn_did,
self.infcx.resolve_vars_if_possible(args),
) else {
return;
};
let param = match find_param_with_region(tcx, self.mir_def_id(), f, o) {
Some(param) => param,
None => return,
let Some(param) = find_param_with_region(tcx, self.mir_def_id(), f, o) else {
return;
};
debug!(?param);

View file

@ -2,6 +2,7 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![deny(clippy::manual_let_else)]
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(file_buffered)]

View file

@ -67,12 +67,11 @@ impl<'a, 'tcx> Visitor<'tcx> for AccessFactsExtractor<'a, 'tcx> {
match context {
PlaceContext::NonMutatingUse(_)
| PlaceContext::MutatingUse(MutatingUseContext::Borrow) => {
let path = match self.move_data.rev_lookup.find(place.as_ref()) {
LookupResult::Exact(path) | LookupResult::Parent(Some(path)) => path,
_ => {
// There's no path access to emit.
return;
}
let (LookupResult::Exact(path) | LookupResult::Parent(Some(path))) =
self.move_data.rev_lookup.find(place.as_ref())
else {
// There's no path access to emit.
return;
};
debug!("AccessFactsExtractor - emit path access ({path:?}, {location:?})");
self.facts.path_accessed_at_base.push((path, self.location_to_index(location)));

View file

@ -80,7 +80,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let OutlivesConstraint { sup, sub, locations, category, span, .. } = constraint;
let (name, arg) = match locations {
Locations::All(span) => {
("All", tcx.sess.source_map().span_to_embeddable_string(*span))
("All", tcx.sess.source_map().span_to_diagnostic_string(*span))
}
Locations::Single(loc) => ("Single", format!("{loc:?}")),
};

View file

@ -68,13 +68,10 @@ pub(crate) fn expand_file(
let topmost = cx.expansion_cause().unwrap_or(sp);
let loc = cx.source_map().lookup_char_pos(topmost.lo());
use rustc_session::RemapFileNameExt;
use rustc_session::config::RemapPathScopeComponents;
use rustc_span::RemapPathScopeComponents;
ExpandResult::Ready(MacEager::expr(cx.expr_str(
topmost,
Symbol::intern(
&loc.file.name.for_scope(cx.sess, RemapPathScopeComponents::MACRO).to_string_lossy(),
),
Symbol::intern(&loc.file.name.display(RemapPathScopeComponents::MACRO).to_string_lossy()),
)))
}

View file

@ -11,7 +11,7 @@ use rustc_errors::{Applicability, Diag, Level};
use rustc_expand::base::*;
use rustc_hir::Attribute;
use rustc_hir::attrs::AttributeKind;
use rustc_span::{ErrorGuaranteed, FileNameDisplayPreference, Ident, Span, Symbol, sym};
use rustc_span::{ErrorGuaranteed, Ident, RemapPathScopeComponents, Span, Symbol, sym};
use thin_vec::{ThinVec, thin_vec};
use tracing::debug;
@ -445,7 +445,7 @@ fn get_location_info(cx: &ExtCtxt<'_>, fn_: &ast::Fn) -> (Symbol, usize, usize,
cx.sess.source_map().span_to_location_info(span);
let file_name = match source_file {
Some(sf) => sf.name.display(FileNameDisplayPreference::Remapped).to_string(),
Some(sf) => sf.name.display(RemapPathScopeComponents::MACRO).to_string(),
None => "no-location".to_string(),
};

View file

@ -6,7 +6,10 @@ use std::path::{Component, Path};
use cranelift_codegen::MachSrcLoc;
use cranelift_codegen::binemit::CodeOffset;
use gimli::write::{FileId, FileInfo, LineProgram, LineString, LineStringTable};
use rustc_span::{FileName, Pos, SourceFile, SourceFileAndLine, SourceFileHashAlgorithm, hygiene};
use rustc_span::{
FileName, Pos, RemapPathScopeComponents, SourceFile, SourceFileAndLine,
SourceFileHashAlgorithm, hygiene,
};
use crate::debuginfo::FunctionDebugContext;
use crate::debuginfo::emit::address_for_func;
@ -95,7 +98,7 @@ impl DebugContext {
match &source_file.name {
FileName::Real(path) => {
let (dir_path, file_name) =
split_path_dir_and_file(path.to_path(self.filename_display_preference));
split_path_dir_and_file(path.path(RemapPathScopeComponents::DEBUGINFO));
let dir_name = osstr_as_utf8_bytes(dir_path.as_os_str());
let file_name = osstr_as_utf8_bytes(file_name);

View file

@ -21,7 +21,7 @@ use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefIdMap;
use rustc_session::Session;
use rustc_session::config::DebugInfo;
use rustc_span::{FileNameDisplayPreference, SourceFileHash, StableSourceFileId};
use rustc_span::{RemapPathScopeComponents, SourceFileHash, StableSourceFileId};
use rustc_target::callconv::FnAbi;
pub(crate) use self::emit::{DebugReloc, DebugRelocName};
@ -44,7 +44,6 @@ pub(crate) struct DebugContext {
namespace_map: DefIdMap<UnitEntryId>,
array_size_type: Option<UnitEntryId>,
filename_display_preference: FileNameDisplayPreference,
embed_source: bool,
}
@ -102,18 +101,18 @@ impl DebugContext {
let mut dwarf = DwarfUnit::new(encoding);
use rustc_session::config::RemapPathScopeComponents;
let filename_display_preference =
tcx.sess.filename_display_preference(RemapPathScopeComponents::DEBUGINFO);
let producer = producer(tcx.sess);
let comp_dir =
tcx.sess.opts.working_dir.to_string_lossy(filename_display_preference).to_string();
let comp_dir = tcx
.sess
.source_map()
.working_dir()
.path(RemapPathScopeComponents::DEBUGINFO)
.to_string_lossy();
let (name, file_info) = match tcx.sess.local_crate_source_file() {
Some(path) => {
let name = path.to_string_lossy(filename_display_preference).to_string();
let name =
path.path(RemapPathScopeComponents::DEBUGINFO).to_string_lossy().into_owned();
(name, None)
}
None => (tcx.crate_name(LOCAL_CRATE).to_string(), None),
@ -137,7 +136,7 @@ impl DebugContext {
{
let name = dwarf.strings.add(format!("{name}/@/{cgu_name}"));
let comp_dir = dwarf.strings.add(comp_dir);
let comp_dir = dwarf.strings.add(&*comp_dir);
let root = dwarf.unit.root();
let root = dwarf.unit.get_mut(root);
@ -180,7 +179,6 @@ impl DebugContext {
stack_pointer_register,
namespace_map: DefIdMap::default(),
array_size_type,
filename_display_preference,
embed_source,
})
}

View file

@ -130,11 +130,9 @@ impl UnwindContext {
return;
}
let unwind_info = if let Some(unwind_info) =
let Some(unwind_info) =
context.compiled_code().unwrap().create_unwind_info(module.isa()).unwrap()
{
unwind_info
} else {
else {
return;
};

View file

@ -29,11 +29,7 @@ pub(crate) fn maybe_known_branch_taken(
arg: Value,
test_zero: bool,
) -> Option<bool> {
let arg_inst = if let ValueDef::Result(arg_inst, 0) = bcx.func.dfg.value_def(arg) {
arg_inst
} else {
return None;
};
let ValueDef::Result(arg_inst, 0) = bcx.func.dfg.value_def(arg) else { return None };
match bcx.func.dfg.insts[arg_inst] {
InstructionData::UnaryImm { opcode: Opcode::Iconst, imm } => {

View file

@ -297,29 +297,11 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
let pos = span.lo();
let DebugLoc { file, line, col } = self.lookup_debug_loc(pos);
match file.name {
rustc_span::FileName::Real(ref name) => match *name {
rustc_span::RealFileName::LocalPath(ref name) => {
if let Some(name) = name.to_str() {
self.context.new_location(name, line as i32, col as i32)
} else {
Location::null()
}
}
rustc_span::RealFileName::Remapped {
ref local_path,
virtual_name: ref _unused,
} => {
if let Some(name) = local_path.as_ref() {
if let Some(name) = name.to_str() {
self.context.new_location(name, line as i32, col as i32)
} else {
Location::null()
}
} else {
Location::null()
}
}
},
rustc_span::FileName::Real(ref name) => self.context.new_location(
name.path(rustc_span::RemapPathScopeComponents::DEBUGINFO).to_string_lossy(),
line as i32,
col as i32,
),
_ => Location::null(),
}
}

View file

@ -460,9 +460,10 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
}
sym::bitreverse => self.bit_reverse(width, args[0].immediate()),
sym::rotate_left | sym::rotate_right => {
// TODO(antoyo): implement using algorithm from:
// Using optimized branchless algorithm from:
// https://blog.regehr.org/archives/1063
// for other platforms.
// This implementation uses the pattern (x<<n) | (x>>(-n&(width-1)))
// which generates efficient code for other platforms.
let is_left = name == sym::rotate_left;
let val = args[0].immediate();
let raw_shift = args[1].immediate();

View file

@ -774,24 +774,23 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
return Err(());
}};
}
let (elem_ty_str, elem_ty, cast_type) = if let ty::Float(ref f) = *in_elem.kind() {
let elem_ty = bx.cx.type_float_from_ty(*f);
match f.bit_width() {
16 => ("", elem_ty, Some(bx.cx.double_type)),
32 => ("f", elem_ty, None),
64 => ("", elem_ty, None),
_ => {
return_error!(InvalidMonomorphization::FloatingPointVector {
span,
name,
f_ty: *f,
in_ty
});
}
}
} else {
let ty::Float(ref f) = *in_elem.kind() else {
return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty });
};
let elem_ty = bx.cx.type_float_from_ty(*f);
let (elem_ty_str, elem_ty, cast_type) = match f.bit_width() {
16 => ("", elem_ty, Some(bx.cx.double_type)),
32 => ("f", elem_ty, None),
64 => ("", elem_ty, None),
_ => {
return_error!(InvalidMonomorphization::FloatingPointVector {
span,
name,
f_ty: *f,
in_ty
});
}
};
let vec_ty = bx.cx.type_vector(elem_ty, in_len);

View file

@ -21,10 +21,8 @@ use rustc_errors::{DiagCtxtHandle, Level};
use rustc_fs_util::{link_or_copy, path_to_c_string};
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_session::config::{
self, Lto, OutputType, Passes, RemapPathScopeComponents, SplitDwarfKind, SwitchWithOptPath,
};
use rustc_span::{BytePos, InnerSpan, Pos, SpanData, SyntaxContext, sym};
use rustc_session::config::{self, Lto, OutputType, Passes, SplitDwarfKind, SwitchWithOptPath};
use rustc_span::{BytePos, InnerSpan, Pos, RemapPathScopeComponents, SpanData, SyntaxContext, sym};
use rustc_target::spec::{
Arch, CodeModel, FloatAbi, RelocModel, SanitizerSet, SplitDebuginfo, TlsModel,
};
@ -248,6 +246,7 @@ pub(crate) fn target_machine_factory(
!sess.opts.unstable_opts.use_ctors_section.unwrap_or(sess.target.use_ctors_section);
let path_mapping = sess.source_map().path_mapping().clone();
let working_dir = sess.source_map().working_dir().clone();
let use_emulated_tls = matches!(sess.tls_model(), TlsModel::Emulated);
@ -271,9 +270,6 @@ pub(crate) fn target_machine_factory(
}
};
let file_name_display_preference =
sess.filename_display_preference(RemapPathScopeComponents::DEBUGINFO);
let use_wasm_eh = wants_wasm_eh(sess);
let prof = SelfProfilerRef::clone(&sess.prof);
@ -284,8 +280,9 @@ pub(crate) fn target_machine_factory(
let path_to_cstring_helper = |path: Option<PathBuf>| -> CString {
let path = path.unwrap_or_default();
let path = path_mapping
.to_real_filename(path)
.to_string_lossy(file_name_display_preference)
.to_real_filename(&working_dir, path)
.path(RemapPathScopeComponents::DEBUGINFO)
.to_string_lossy()
.into_owned();
CString::new(path).unwrap()
};

View file

@ -7,9 +7,7 @@ use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, ConstCodegenMethods};
use rustc_data_structures::fx::FxIndexMap;
use rustc_index::IndexVec;
use rustc_middle::ty::TyCtxt;
use rustc_session::RemapFileNameExt;
use rustc_session::config::RemapPathScopeComponents;
use rustc_span::{SourceFile, StableSourceFileId};
use rustc_span::{RemapPathScopeComponents, SourceFile, StableSourceFileId};
use tracing::debug;
use crate::common::CodegenCx;
@ -127,10 +125,7 @@ impl GlobalFileTable {
for file in all_files {
raw_file_table.entry(file.stable_id).or_insert_with(|| {
file.name
.for_scope(tcx.sess, RemapPathScopeComponents::COVERAGE)
.to_string_lossy()
.into_owned()
file.name.display(RemapPathScopeComponents::COVERAGE).to_string_lossy().into_owned()
});
}
@ -145,9 +140,10 @@ impl GlobalFileTable {
// resolve any other entries that are stored as relative paths.
let base_dir = tcx
.sess
.opts
.working_dir
.for_scope(tcx.sess, RemapPathScopeComponents::COVERAGE)
.psess
.source_map()
.working_dir()
.path(RemapPathScopeComponents::COVERAGE)
.to_string_lossy();
table.push(base_dir.as_ref());

View file

@ -1,7 +1,7 @@
use std::borrow::Cow;
use std::fmt::{self, Write};
use std::hash::{Hash, Hasher};
use std::path::{Path, PathBuf};
use std::path::PathBuf;
use std::sync::Arc;
use std::{iter, ptr};
@ -19,9 +19,7 @@ use rustc_middle::ty::{
self, AdtKind, CoroutineArgsExt, ExistentialTraitRef, Instance, Ty, TyCtxt, Visibility,
};
use rustc_session::config::{self, DebugInfo, Lto};
use rustc_span::{
DUMMY_SP, FileName, FileNameDisplayPreference, SourceFile, Span, Symbol, hygiene,
};
use rustc_span::{DUMMY_SP, FileName, RemapPathScopeComponents, SourceFile, Span, Symbol, hygiene};
use rustc_symbol_mangling::typeid_for_trait_ref;
use rustc_target::spec::DebuginfoKind;
use smallvec::smallvec;
@ -555,79 +553,38 @@ pub(crate) fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFi
) -> &'ll DIFile {
debug!(?source_file.name);
let filename_display_preference =
cx.sess().filename_display_preference(RemapPathScopeComponents::DEBUGINFO);
use rustc_session::config::RemapPathScopeComponents;
let (directory, file_name) = match &source_file.name {
FileName::Real(filename) => {
let working_directory = &cx.sess().opts.working_dir;
debug!(?working_directory);
let (working_directory, embeddable_name) =
filename.embeddable_name(RemapPathScopeComponents::DEBUGINFO);
if filename_display_preference == FileNameDisplayPreference::Remapped {
let filename = cx
.sess()
.source_map()
.path_mapping()
.to_embeddable_absolute_path(filename.clone(), working_directory);
debug!(?working_directory, ?embeddable_name);
// Construct the absolute path of the file
let abs_path = filename.remapped_path_if_available();
debug!(?abs_path);
if let Ok(rel_path) =
abs_path.strip_prefix(working_directory.remapped_path_if_available())
{
// If the compiler's working directory (which also is the DW_AT_comp_dir of
// the compilation unit) is a prefix of the path we are about to emit, then
// only emit the part relative to the working directory. Because of path
// remapping we sometimes see strange things here: `abs_path` might
// actually look like a relative path (e.g.
// `<crate-name-and-version>/src/lib.rs`), so if we emit it without taking
// the working directory into account, downstream tooling will interpret it
// as `<working-directory>/<crate-name-and-version>/src/lib.rs`, which
// makes no sense. Usually in such cases the working directory will also be
// remapped to `<crate-name-and-version>` or some other prefix of the path
// we are remapping, so we end up with
// `<crate-name-and-version>/<crate-name-and-version>/src/lib.rs`.
// By moving the working directory portion into the `directory` part of the
// DIFile, we allow LLVM to emit just the relative path for DWARF, while
// still emitting the correct absolute path for CodeView.
(
working_directory.to_string_lossy(FileNameDisplayPreference::Remapped),
rel_path.to_string_lossy().into_owned(),
)
} else {
("".into(), abs_path.to_string_lossy().into_owned())
}
if let Ok(rel_path) = embeddable_name.strip_prefix(working_directory) {
// If the compiler's working directory (which also is the DW_AT_comp_dir of
// the compilation unit) is a prefix of the path we are about to emit, then
// only emit the part relative to the working directory. Because of path
// remapping we sometimes see strange things here: `abs_path` might
// actually look like a relative path (e.g.
// `<crate-name-and-version>/src/lib.rs`), so if we emit it without taking
// the working directory into account, downstream tooling will interpret it
// as `<working-directory>/<crate-name-and-version>/src/lib.rs`, which
// makes no sense. Usually in such cases the working directory will also be
// remapped to `<crate-name-and-version>` or some other prefix of the path
// we are remapping, so we end up with
// `<crate-name-and-version>/<crate-name-and-version>/src/lib.rs`.
//
// By moving the working directory portion into the `directory` part of the
// DIFile, we allow LLVM to emit just the relative path for DWARF, while
// still emitting the correct absolute path for CodeView.
(working_directory.to_string_lossy(), rel_path.to_string_lossy().into_owned())
} else {
let working_directory = working_directory.local_path_if_available();
let filename = filename.local_path_if_available();
debug!(?working_directory, ?filename);
let abs_path: Cow<'_, Path> = if filename.is_absolute() {
filename.into()
} else {
let mut p = PathBuf::new();
p.push(working_directory);
p.push(filename);
p.into()
};
if let Ok(rel_path) = abs_path.strip_prefix(working_directory) {
(
working_directory.to_string_lossy(),
rel_path.to_string_lossy().into_owned(),
)
} else {
("".into(), abs_path.to_string_lossy().into_owned())
}
("".into(), embeddable_name.to_string_lossy().into_owned())
}
}
other => {
debug!(?other);
("".into(), other.display(filename_display_preference).to_string())
("".into(), other.display(RemapPathScopeComponents::DEBUGINFO).to_string())
}
};
@ -889,12 +846,10 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(
codegen_unit_name: &str,
debug_context: &CodegenUnitDebugContext<'ll, 'tcx>,
) -> &'ll DIDescriptor {
use rustc_session::RemapFileNameExt;
use rustc_session::config::RemapPathScopeComponents;
let mut name_in_debuginfo = tcx
.sess
.local_crate_source_file()
.map(|src| src.for_scope(&tcx.sess, RemapPathScopeComponents::DEBUGINFO).to_path_buf())
.map(|src| src.path(RemapPathScopeComponents::DEBUGINFO).to_path_buf())
.unwrap_or_else(|| PathBuf::from(tcx.crate_name(LOCAL_CRATE).as_str()));
// To avoid breaking split DWARF, we need to ensure that each codegen unit
@ -923,12 +878,7 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(
let producer = format!("clang LLVM ({rustc_producer})");
let name_in_debuginfo = name_in_debuginfo.to_string_lossy();
let work_dir = tcx
.sess
.opts
.working_dir
.for_scope(tcx.sess, RemapPathScopeComponents::DEBUGINFO)
.to_string_lossy();
let work_dir = tcx.sess.psess.source_map().working_dir();
let output_filenames = tcx.output_filenames(());
let split_name = if tcx.sess.target_can_use_split_dwarf()
&& let Some(f) = output_filenames.split_dwarf_path(
@ -938,14 +888,15 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(
tcx.sess.invocation_temp.as_deref(),
) {
// We get a path relative to the working directory from split_dwarf_path
Some(tcx.sess.source_map().path_mapping().to_real_filename(f))
Some(tcx.sess.source_map().path_mapping().to_real_filename(work_dir, f))
} else {
None
};
let split_name = split_name
.as_ref()
.map(|f| f.for_scope(tcx.sess, RemapPathScopeComponents::DEBUGINFO).to_string_lossy())
.map(|f| f.path(RemapPathScopeComponents::DEBUGINFO).to_string_lossy())
.unwrap_or_default();
let work_dir = work_dir.path(RemapPathScopeComponents::DEBUGINFO).to_string_lossy();
let kind = DebugEmissionKind::from_generic(tcx.sess.opts.debuginfo);
let dwarf_version = tcx.sess.dwarf_version();

View file

@ -1756,11 +1756,10 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
}};
}
let elem_ty = if let ty::Float(f) = in_elem.kind() {
bx.cx.type_float_from_ty(*f)
} else {
let ty::Float(f) = in_elem.kind() else {
return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty });
};
let elem_ty = bx.cx.type_float_from_ty(*f);
let vec_ty = bx.type_vector(elem_ty, in_len);

View file

@ -721,11 +721,10 @@ pub fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
};
// First read the ret symbol from the attribute
let ret_symbol = if let MetaItemInner::MetaItem(MetaItem { path: p1, .. }) = ret_activity {
p1.segments.first().unwrap().ident
} else {
let MetaItemInner::MetaItem(MetaItem { path: p1, .. }) = ret_activity else {
span_bug!(attr.span(), "rustc_autodiff attribute must contain the return activity");
};
let ret_symbol = p1.segments.first().unwrap().ident;
// Then parse it into an actual DiffActivity
let Ok(ret_activity) = DiffActivity::from_str(ret_symbol.as_str()) else {

View file

@ -208,15 +208,10 @@ impl<'tcx> CompileTimeInterpCx<'tcx> {
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
use rustc_session::RemapFileNameExt;
use rustc_session::config::RemapPathScopeComponents;
use rustc_span::RemapPathScopeComponents;
(
Symbol::intern(
&caller
.file
.name
.for_scope(self.tcx.sess, RemapPathScopeComponents::DIAGNOSTICS)
.to_string_lossy(),
&caller.file.name.display(RemapPathScopeComponents::DIAGNOSTICS).to_string_lossy(),
),
u32::try_from(caller.line).unwrap(),
u32::try_from(caller.col_display).unwrap().checked_add(1).unwrap(),

View file

@ -1,5 +1,6 @@
// tidy-alphabetical-start
#![allow(rustc::diagnostic_outside_of_impl)]
#![deny(clippy::manual_let_else)]
#![feature(array_try_map)]
#![feature(assert_matches)]
#![feature(box_patterns)]

View file

@ -75,6 +75,7 @@ impl_dyn_send!(
[std::sync::Mutex<T> where T: ?Sized+ DynSend]
[std::sync::mpsc::Sender<T> where T: DynSend]
[std::sync::Arc<T> where T: ?Sized + DynSync + DynSend]
[std::sync::Weak<T> where T: ?Sized + DynSync + DynSend]
[std::sync::LazyLock<T, F> where T: DynSend, F: DynSend]
[std::collections::HashSet<K, S> where K: DynSend, S: DynSend]
[std::collections::HashMap<K, V, S> where K: DynSend, V: DynSend, S: DynSend]
@ -157,6 +158,7 @@ impl_dyn_sync!(
[std::sync::OnceLock<T> where T: DynSend + DynSync]
[std::sync::Mutex<T> where T: ?Sized + DynSend]
[std::sync::Arc<T> where T: ?Sized + DynSync + DynSend]
[std::sync::Weak<T> where T: ?Sized + DynSync + DynSend]
[std::sync::LazyLock<T, F> where T: DynSend + DynSync, F: DynSend]
[std::collections::HashSet<K, S> where K: DynSync, S: DynSync]
[std::collections::HashMap<K, V, S> where K: DynSync, V: DynSync, S: DynSync]

View file

@ -181,7 +181,7 @@ impl<'tcx> pprust_hir::PpAnn for HirTypedAnn<'tcx> {
}
fn get_source(sess: &Session) -> (String, FileName) {
let src_name = sess.io.input.source_name();
let src_name = sess.io.input.file_name(&sess);
let src = String::clone(
sess.source_map()
.get_source_file(&src_name)

View file

@ -1,3 +1,5 @@
#### Note: this error code is no longer emitted by the compiler.
The `not` cfg-predicate was malformed.
Erroneous code example (using `cargo doc`):

View file

@ -11,7 +11,7 @@
use std::error::Report;
use std::io::{self, Write};
use std::path::Path;
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
use std::vec;
@ -20,9 +20,9 @@ use derive_setters::Setters;
use rustc_data_structures::sync::IntoDynSyncSend;
use rustc_error_messages::FluentArgs;
use rustc_lint_defs::Applicability;
use rustc_span::Span;
use rustc_span::hygiene::ExpnData;
use rustc_span::source_map::{FilePathMapping, SourceMap};
use rustc_span::{FileName, RealFileName, Span};
use serde::Serialize;
use crate::annotate_snippet_emitter_writer::AnnotateSnippetEmitter;
@ -490,8 +490,14 @@ impl DiagnosticSpan {
None => {
span = rustc_span::DUMMY_SP;
empty_source_map = Arc::new(SourceMap::new(FilePathMapping::empty()));
empty_source_map
.new_source_file(std::path::PathBuf::from("empty.rs").into(), String::new());
empty_source_map.new_source_file(
FileName::Real(
empty_source_map
.path_mapping()
.to_real_filename(&RealFileName::empty(), PathBuf::from("empty.rs")),
),
String::new(),
);
&empty_source_map
}
};

View file

@ -36,11 +36,15 @@ impl<T: Write> Write for Shared<T> {
}
}
fn filename(sm: &SourceMap, path: &str) -> FileName {
FileName::Real(sm.path_mapping().to_real_filename(sm.working_dir(), PathBuf::from(path)))
}
/// Test the span yields correct positions in JSON.
fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
rustc_span::create_default_session_globals_then(|| {
let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));
sm.new_source_file(Path::new("test.rs").to_owned().into(), code.to_owned());
sm.new_source_file(filename(&sm, "test.rs"), code.to_owned());
let translator =
Translator::with_fallback_bundle(vec![crate::DEFAULT_LOCALE_RESOURCE], false);

View file

@ -470,7 +470,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
FileName::Real(name) => name
.into_local_path()
.expect("attempting to resolve a file path in an external file"),
other => PathBuf::from(other.prefer_local().to_string()),
other => PathBuf::from(other.prefer_local_unconditionally().to_string()),
};
let dir_path = file_path.parent().unwrap_or(&file_path).to_owned();
self.cx.root_path = dir_path.clone();

View file

@ -788,11 +788,10 @@ pub fn compile_declarative_macro(
let lhs_span = lhs_tt.span();
// Convert the lhs into `MatcherLoc` form, which is better for doing the
// actual matching.
let lhs = if let mbe::TokenTree::Delimited(.., delimited) = lhs_tt {
mbe::macro_parser::compute_locs(&delimited.tts)
} else {
let mbe::TokenTree::Delimited(.., delimited) = lhs_tt else {
return dummy_syn_ext(guar.unwrap());
};
let lhs = mbe::macro_parser::compute_locs(&delimited.tts);
if let Some(args) = args {
let args_span = args.span();
let mbe::TokenTree::Delimited(.., delimited) = args else {

View file

@ -138,10 +138,7 @@ pub(crate) fn update_macro_stats(
if false {
let name = ExpnKind::Macro(macro_kind, name).descr();
let crate_name = &ecx.ecfg.crate_name;
let span = ecx
.sess
.source_map()
.span_to_string(span, rustc_span::FileNameDisplayPreference::Local);
let span = ecx.sess.source_map().span_to_diagnostic_string(span);
eprint!(
"\
-------------------------------\n\

View file

@ -4,6 +4,7 @@
// tidy-alphabetical-start
#![cfg_attr(bootstrap, feature(debug_closure_helpers))]
#![deny(clippy::manual_let_else)]
#![feature(associated_type_defaults)]
#![feature(closure_track_caller)]
#![feature(const_default)]

View file

@ -1551,15 +1551,15 @@ fn const_param_default<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
let default_ct = match tcx.hir_node_by_def_id(def_id) {
hir::Node::GenericParam(hir::GenericParam {
kind: hir::GenericParamKind::Const { default: Some(ct), .. },
..
}) => ct,
_ => span_bug!(
let hir::Node::GenericParam(hir::GenericParam {
kind: hir::GenericParamKind::Const { default: Some(default_ct), .. },
..
}) = tcx.hir_node_by_def_id(def_id)
else {
span_bug!(
tcx.def_span(def_id),
"`const_param_default` expected a generic parameter with a constant"
),
)
};
let icx = ItemCtxt::new(tcx, def_id);
let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);

View file

@ -188,29 +188,26 @@ fn remap_gat_vars_and_recurse_into_nested_projections<'tcx>(
for (param, var) in std::iter::zip(&generics.own_params, gat_vars) {
let existing = match var.kind() {
ty::GenericArgKind::Lifetime(re) => {
if let ty::RegionKind::ReBound(ty::BoundVarIndexKind::Bound(ty::INNERMOST), bv) =
let ty::RegionKind::ReBound(ty::BoundVarIndexKind::Bound(ty::INNERMOST), bv) =
re.kind()
{
mapping.insert(bv.var, tcx.mk_param_from_def(param))
} else {
else {
return None;
}
};
mapping.insert(bv.var, tcx.mk_param_from_def(param))
}
ty::GenericArgKind::Type(ty) => {
if let ty::Bound(ty::BoundVarIndexKind::Bound(ty::INNERMOST), bv) = *ty.kind() {
mapping.insert(bv.var, tcx.mk_param_from_def(param))
} else {
let ty::Bound(ty::BoundVarIndexKind::Bound(ty::INNERMOST), bv) = *ty.kind() else {
return None;
}
};
mapping.insert(bv.var, tcx.mk_param_from_def(param))
}
ty::GenericArgKind::Const(ct) => {
if let ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(ty::INNERMOST), bv) =
let ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(ty::INNERMOST), bv) =
ct.kind()
{
mapping.insert(bv.var, tcx.mk_param_from_def(param))
} else {
else {
return None;
}
};
mapping.insert(bv.var, tcx.mk_param_from_def(param))
}
};

View file

@ -763,9 +763,8 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
&self,
err: &mut Diag<'_, impl EmissionGuarantee>,
) {
let trait_ = match self.tcx.trait_of_assoc(self.def_id) {
Some(def_id) => def_id,
None => return,
let Some(trait_) = self.tcx.trait_of_assoc(self.def_id) else {
return;
};
// Skip suggestion when the associated function is itself generic, it is unclear
@ -1077,15 +1076,11 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
/// Builds the `type defined here` message.
fn show_definition(&self, err: &mut Diag<'_, impl EmissionGuarantee>) {
let mut spans: MultiSpan = if let Some(def_span) = self.tcx.def_ident_span(self.def_id) {
if self.tcx.sess.source_map().is_span_accessible(def_span) {
def_span.into()
} else {
return;
}
} else {
let Some(def_span) = self.tcx.def_ident_span(self.def_id) else { return };
if !self.tcx.sess.source_map().is_span_accessible(def_span) {
return;
};
let mut spans: MultiSpan = def_span.into();
let msg = {
let def_kind = self.tcx.def_descr(self.def_id);

View file

@ -1749,10 +1749,8 @@ fn generics_args_err_extend<'a>(
GenericsArgsErrExtend::SelfTyAlias { def_id, span } => {
let ty = tcx.at(span).type_of(def_id).instantiate_identity();
let span_of_impl = tcx.span_of_impl(def_id);
let def_id = match *ty.kind() {
ty::Adt(self_def, _) => self_def.did(),
_ => return,
};
let ty::Adt(self_def, _) = *ty.kind() else { return };
let def_id = self_def.did();
let type_name = tcx.item_name(def_id);
let span_of_ty = tcx.def_ident_span(def_id);

View file

@ -59,6 +59,7 @@ This API is completely unstable and subject to change.
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
#![cfg_attr(bootstrap, feature(debug_closure_helpers))]
#![deny(clippy::manual_let_else)]
#![feature(assert_matches)]
#![feature(gen_blocks)]
#![feature(if_let_guard)]

View file

@ -458,15 +458,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{
// Actually need to unwrap one more layer of HIR to get to
// the _real_ closure...
if let hir::Node::Expr(&hir::Expr {
let hir::Node::Expr(&hir::Expr {
kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }),
..
}) = self.tcx.parent_hir_node(parent_hir_id)
{
fn_decl_span
} else {
else {
return;
}
};
fn_decl_span
} else {
return;
};

View file

@ -415,11 +415,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
});
Some(self.resolve_vars_if_possible(possible_rcvr_ty))
});
if let Some(rcvr_ty) = possible_rcvr_ty {
rcvr_ty
} else {
return false;
}
let Some(rcvr_ty) = possible_rcvr_ty else { return false };
rcvr_ty
}
};

View file

@ -3180,6 +3180,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.span_label(within_macro_span, "due to this macro variable");
}
// Check if there is an associated function with the same name.
if let Some(def_id) = base_ty.peel_refs().ty_adt_def().map(|d| d.did()) {
for impl_def_id in self.tcx.inherent_impls(def_id) {
for item in self.tcx.associated_items(impl_def_id).in_definition_order() {
if let ExprKind::Field(base_expr, _) = expr.kind
&& item.name() == field.name
&& matches!(item.kind, ty::AssocKind::Fn { has_self: false, .. })
{
err.span_label(field.span, "this is an associated function, not a method");
err.note("found the following associated function; to be used as method, it must have a `self` parameter");
let impl_ty = self.tcx.type_of(impl_def_id).instantiate_identity();
err.span_note(
self.tcx.def_span(item.def_id),
format!("the candidate is defined in an impl for the type `{impl_ty}`"),
);
let ty_str = match base_ty.peel_refs().kind() {
ty::Adt(def, args) => self.tcx.def_path_str_with_args(def.did(), args),
_ => base_ty.peel_refs().to_string(),
};
err.multipart_suggestion(
"use associated function syntax instead",
vec![
(base_expr.span, ty_str),
(base_expr.span.between(field.span), "::".to_string()),
],
Applicability::MaybeIncorrect,
);
return err;
}
}
}
}
// try to add a suggestion in case the field is a nested field of a field of the Adt
let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id();
let (ty, unwrap) = if let ty::Adt(def, args) = base_ty.kind()

View file

@ -1561,19 +1561,15 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
base_place: PlaceWithHirId<'tcx>,
) -> Result<PlaceWithHirId<'tcx>, Cx::Error> {
let base_curr_ty = base_place.place.ty();
let deref_ty = match self
let Some(deref_ty) = self
.cx
.structurally_resolve_type(self.cx.tcx().hir_span(base_place.hir_id), base_curr_ty)
.builtin_deref(true)
{
Some(ty) => ty,
None => {
debug!("explicit deref of non-derefable type: {:?}", base_curr_ty);
return Err(self.cx.report_bug(
self.cx.tcx().hir_span(node),
"explicit deref of non-derefable type",
));
}
else {
debug!("explicit deref of non-derefable type: {:?}", base_curr_ty);
return Err(self
.cx
.report_bug(self.cx.tcx().hir_span(node), "explicit deref of non-derefable type"));
};
let mut projections = base_place.place.projections;
projections.push(Projection { kind: ProjectionKind::Deref, ty: deref_ty });

View file

@ -48,33 +48,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
let uninstantiated_pred = match flavor {
ClauseFlavor::Where => {
ClauseFlavor::Where
if let Some(pred) = self
.tcx
.predicates_of(def_id)
.instantiate_identity(self.tcx)
.predicates
.into_iter()
.nth(idx)
{
pred
} else {
return false;
}
.nth(idx) =>
{
pred
}
ClauseFlavor::Const => {
ClauseFlavor::Const
if let Some((pred, _)) = self
.tcx
.const_conditions(def_id)
.instantiate_identity(self.tcx)
.into_iter()
.nth(idx)
{
pred.to_host_effect_clause(self.tcx, ty::BoundConstness::Maybe)
} else {
return false;
}
.nth(idx) =>
{
pred.to_host_effect_clause(self.tcx, ty::BoundConstness::Maybe)
}
_ => return false,
};
let generics = self.tcx.generics_of(def_id);

View file

@ -1467,11 +1467,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => None,
}
});
if let Some(new_def_id) = new_def_id {
def_id = new_def_id;
} else {
return;
}
let Some(new_def_id) = new_def_id else { return };
def_id = new_def_id;
}
}
}

View file

@ -1795,7 +1795,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Some(ty),
hir::Path { segments: [segment], .. },
))
| hir::ExprKind::Path(QPath::TypeRelative(ty, segment)) => {
| hir::ExprKind::Path(QPath::TypeRelative(ty, segment))
if let Some(self_ty) = self.typeck_results.borrow().node_type_opt(ty.hir_id)
&& let Ok(pick) = self.probe_for_name(
Mode::Path,
@ -1805,12 +1805,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self_ty,
expr.hir_id,
ProbeScope::TraitsInScope,
)
{
(pick.item, segment)
} else {
return false;
}
) =>
{
(pick.item, segment)
}
hir::ExprKind::Path(QPath::Resolved(
None,
@ -1821,16 +1818,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if old_item_name != segment.ident.name {
return false;
}
if let Some(item) = self
let Some(item) = self
.tcx
.associated_items(self.tcx.parent(old_def_id))
.filter_by_name_unhygienic(capitalized_name)
.next()
{
(*item, segment)
} else {
else {
return false;
}
};
(*item, segment)
}
_ => return false,
};

View file

@ -121,13 +121,12 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
len,
)
};
if let Some(len) = len.try_to_target_usize(self.tcx()) {
(len, ty)
} else {
let Some(len) = len.try_to_target_usize(self.tcx()) else {
return Err(NonAsmTypeReason::UnevaluatedSIMDArrayLength(
field.did, len,
));
}
};
(len, ty)
}
_ => (fields.len() as u64, elem_ty),
};

View file

@ -1,4 +1,5 @@
// tidy-alphabetical-start
#![deny(clippy::manual_let_else)]
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(if_let_guard)]

View file

@ -2511,7 +2511,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
applicability = Applicability::HasPlaceholders;
"(...)".to_owned()
};
err.span_suggestion(
err.span_suggestion_verbose(
sugg_span,
"use associated function syntax instead",
format!("{ty_str}::{item_name}{args}"),
@ -3543,10 +3543,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span: Span,
return_type: Option<Ty<'tcx>>,
) {
let output_ty = match self.err_ctxt().get_impl_future_output_ty(ty) {
Some(output_ty) => self.resolve_vars_if_possible(output_ty),
_ => return,
};
let Some(output_ty) = self.err_ctxt().get_impl_future_output_ty(ty) else { return };
let output_ty = self.resolve_vars_if_possible(output_ty);
let method_exists =
self.method_exists_for_diagnostic(item_name, output_ty, call.hir_id, return_type);
debug!("suggest_await_before_method: is_method_exist={}", method_exists);

View file

@ -40,8 +40,7 @@ use rustc_session::output::{collect_crate_types, filename_for_input};
use rustc_session::parse::feature_err;
use rustc_session::search_paths::PathKind;
use rustc_span::{
DUMMY_SP, ErrorGuaranteed, ExpnKind, FileName, SourceFileHash, SourceFileHashAlgorithm, Span,
Symbol, sym,
DUMMY_SP, ErrorGuaranteed, ExpnKind, SourceFileHash, SourceFileHashAlgorithm, Span, Symbol, sym,
};
use rustc_trait_selection::{solve, traits};
use tracing::{info, instrument};
@ -595,7 +594,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P
.filter(|fmap| !fmap.is_imported())
.map(|fmap| {
(
escape_dep_filename(&fmap.name.prefer_local().to_string()),
escape_dep_filename(&fmap.name.prefer_local_unconditionally().to_string()),
// This needs to be unnormalized,
// as external tools wouldn't know how rustc normalizes them
fmap.unnormalized_source_len as u64,
@ -610,10 +609,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P
// (e.g. accessed in proc macros).
let file_depinfo = sess.psess.file_depinfo.borrow();
let normalize_path = |path: PathBuf| {
let file = FileName::from(path);
escape_dep_filename(&file.prefer_local().to_string())
};
let normalize_path = |path: PathBuf| escape_dep_filename(&path.to_string_lossy());
// The entries will be used to declare dependencies between files in a
// Makefile-like output, so the iteration order does not matter.

View file

@ -1072,11 +1072,8 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
cx: &LateContext<'tcx>,
expr: &hir::Expr<'_>,
) -> Option<(Ty<'tcx>, Ty<'tcx>)> {
let def = if let hir::ExprKind::Path(ref qpath) = expr.kind {
cx.qpath_res(qpath, expr.hir_id)
} else {
return None;
};
let hir::ExprKind::Path(ref qpath) = expr.kind else { return None };
let def = cx.qpath_res(qpath, expr.hir_id);
if let Res::Def(DefKind::Fn, did) = def {
if !def_id_is_transmute(cx, did) {
return None;

View file

@ -22,6 +22,7 @@
// tidy-alphabetical-start
#![allow(internal_features)]
#![cfg_attr(bootstrap, feature(array_windows))]
#![deny(clippy::manual_let_else)]
#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(if_let_guard)]

View file

@ -120,10 +120,8 @@ impl Expr2024 {
fn check_ident_token(&mut self, cx: &crate::EarlyContext<'_>, token: &Token) {
debug!("check_ident_token: {:?}", token);
let (sym, edition) = match token.kind {
TokenKind::Ident(sym, _) => (sym, Edition::Edition2024),
_ => return,
};
let TokenKind::Ident(sym, _) = token.kind else { return };
let edition = Edition::Edition2024;
debug!("token.span.edition(): {:?}", token.span.edition());
if token.span.edition() >= edition {

View file

@ -48,6 +48,7 @@ declare_lint_pass! {
ILL_FORMED_ATTRIBUTE_INPUT,
INCOMPLETE_INCLUDE,
INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
INLINE_ALWAYS_MISMATCHING_TARGET_FEATURES,
INLINE_NO_SANITIZE,
INVALID_DOC_ATTRIBUTES,
INVALID_MACRO_EXPORT_ARGUMENTS,

View file

@ -33,8 +33,8 @@ use rustc_session::config::TargetModifier;
use rustc_session::cstore::{CrateSource, ExternCrate};
use rustc_span::hygiene::HygieneDecodeContext;
use rustc_span::{
BlobDecoder, BytePos, ByteSymbol, DUMMY_SP, Pos, SpanData, SpanDecoder, Symbol, SyntaxContext,
kw,
BlobDecoder, BytePos, ByteSymbol, DUMMY_SP, Pos, RemapPathScopeComponents, SpanData,
SpanDecoder, Symbol, SyntaxContext, kw,
};
use tracing::debug;
@ -1669,15 +1669,15 @@ impl<'a> CrateMetadataRef<'a> {
for virtual_dir in virtual_source_base_dir.iter().flatten() {
if let Some(real_dir) = &real_source_base_dir
&& let rustc_span::FileName::Real(old_name) = name
&& let rustc_span::RealFileName::Remapped { local_path: _, virtual_name } =
old_name
&& let Ok(rest) = virtual_name.strip_prefix(virtual_dir)
&& let (_working_dir, embeddable_name) =
old_name.embeddable_name(RemapPathScopeComponents::MACRO)
&& let Ok(rest) = embeddable_name.strip_prefix(virtual_dir)
{
let new_path = real_dir.join(rest);
debug!(
"try_to_translate_virtual_to_real: `{}` -> `{}`",
virtual_name.display(),
embeddable_name.display(),
new_path.display(),
);
@ -1686,17 +1686,12 @@ impl<'a> CrateMetadataRef<'a> {
// Note that this is a special case for imported rust-src paths specified by
// https://rust-lang.github.io/rfcs/3127-trim-paths.html#handling-sysroot-paths.
// Other imported paths are not currently remapped (see #66251).
let (user_remapped, applied) =
tcx.sess.source_map().path_mapping().map_prefix(&new_path);
let new_name = if applied {
rustc_span::RealFileName::Remapped {
local_path: Some(new_path.clone()),
virtual_name: user_remapped.to_path_buf(),
}
} else {
rustc_span::RealFileName::LocalPath(new_path)
};
*old_name = new_name;
*name = rustc_span::FileName::Real(
tcx.sess
.source_map()
.path_mapping()
.to_real_filename(&rustc_span::RealFileName::empty(), new_path),
);
}
}
};
@ -1711,15 +1706,12 @@ impl<'a> CrateMetadataRef<'a> {
&& let Some(real_dir) = real_source_base_dir
&& let rustc_span::FileName::Real(old_name) = name
{
let relative_path = match old_name {
rustc_span::RealFileName::LocalPath(local) => {
local.strip_prefix(real_dir).ok()
}
rustc_span::RealFileName::Remapped { virtual_name, .. } => {
virtual_source_base_dir
.and_then(|virtual_dir| virtual_name.strip_prefix(virtual_dir).ok())
}
};
let (_working_dir, embeddable_path) =
old_name.embeddable_name(RemapPathScopeComponents::MACRO);
let relative_path = embeddable_path.strip_prefix(real_dir).ok().or_else(|| {
virtual_source_base_dir
.and_then(|virtual_dir| embeddable_path.strip_prefix(virtual_dir).ok())
});
debug!(
?relative_path,
?virtual_dir,
@ -1727,10 +1719,10 @@ impl<'a> CrateMetadataRef<'a> {
"simulate_remapped_rust_src_base"
);
if let Some(rest) = relative_path.and_then(|p| p.strip_prefix(subdir).ok()) {
*old_name = rustc_span::RealFileName::Remapped {
local_path: None,
virtual_name: virtual_dir.join(subdir).join(rest),
};
*name =
rustc_span::FileName::Real(rustc_span::RealFileName::from_virtual_path(
&virtual_dir.join(subdir).join(rest),
))
}
}
};

View file

@ -541,8 +541,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
// is done.
let required_source_files = self.required_source_files.take().unwrap();
let working_directory = &self.tcx.sess.opts.working_dir;
let mut adapted = TableBuilder::default();
let local_crate_stable_id = self.tcx.stable_crate_id(LOCAL_CRATE);
@ -567,10 +565,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
match source_file.name {
FileName::Real(ref original_file_name) => {
let adapted_file_name = source_map
.path_mapping()
.to_embeddable_absolute_path(original_file_name.clone(), working_directory);
let mut adapted_file_name = original_file_name.clone();
adapted_file_name.update_for_crate_metadata();
adapted_source_file.name = FileName::Real(adapted_file_name);
}
_ => {

View file

@ -30,6 +30,7 @@
#![allow(rustc::direct_use_of_rustc_type_ir)]
#![allow(rustc::untranslatable_diagnostic)]
#![cfg_attr(bootstrap, feature(array_windows))]
#![deny(clippy::manual_let_else)]
#![feature(allocator_api)]
#![feature(assert_matches)]
#![feature(associated_type_defaults)]

View file

@ -3,9 +3,7 @@ use std::fmt::{self, Debug, Display, Formatter};
use rustc_abi::{HasDataLayout, Size};
use rustc_hir::def_id::DefId;
use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
use rustc_session::RemapFileNameExt;
use rustc_session::config::RemapPathScopeComponents;
use rustc_span::{DUMMY_SP, Span, Symbol};
use rustc_span::{DUMMY_SP, RemapPathScopeComponents, Span, Symbol};
use rustc_type_ir::TypeVisitableExt;
use super::interpret::ReportedErrorInfo;
@ -587,11 +585,7 @@ impl<'tcx> TyCtxt<'tcx> {
let caller = self.sess.source_map().lookup_char_pos(topmost.lo());
self.const_caller_location(
Symbol::intern(
&caller
.file
.name
.for_scope(self.sess, RemapPathScopeComponents::MACRO)
.to_string_lossy(),
&caller.file.name.display(RemapPathScopeComponents::MACRO).to_string_lossy(),
),
caller.line as u32,
caller.col_display as u32 + 1,

View file

@ -504,7 +504,7 @@ fn write_scope_tree(
"{0:1$} // at {2}",
indented_header,
ALIGN,
tcx.sess.source_map().span_to_embeddable_string(span),
tcx.sess.source_map().span_to_diagnostic_string(span),
)?;
} else {
writeln!(w, "{indented_header}")?;
@ -688,7 +688,7 @@ fn write_user_type_annotations(
"| {:?}: user_ty: {}, span: {}, inferred_ty: {}",
index.index(),
annotation.user_ty,
tcx.sess.source_map().span_to_embeddable_string(annotation.span),
tcx.sess.source_map().span_to_diagnostic_string(annotation.span),
with_no_trimmed_paths!(format!("{}", annotation.inferred_ty)),
)?;
}
@ -1420,7 +1420,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
self.push("mir::ConstOperand");
self.push(&format!(
"+ span: {}",
self.tcx.sess.source_map().span_to_embeddable_string(*span)
self.tcx.sess.source_map().span_to_diagnostic_string(*span)
));
if let Some(user_ty) = user_ty {
self.push(&format!("+ user_ty: {user_ty:?}"));
@ -1503,7 +1503,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
}
fn comment(tcx: TyCtxt<'_>, SourceInfo { span, scope }: SourceInfo) -> String {
let location = tcx.sess.source_map().span_to_embeddable_string(span);
let location = tcx.sess.source_map().span_to_diagnostic_string(span);
format!("scope {} at {}", scope.index(), location,)
}

View file

@ -706,12 +706,9 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for MakeSuggestableFolder<'tcx> {
| Bound(_, _)
| Placeholder(_)
| Error(_) => {
if let Some(placeholder) = self.placeholder {
// We replace these with infer (which is passed in from an infcx).
placeholder
} else {
return Err(());
}
let Some(placeholder) = self.placeholder else { return Err(()) };
// We replace these with infer (which is passed in from an infcx).
placeholder
}
Alias(Opaque, AliasTy { def_id, .. }) => {

View file

@ -25,6 +25,7 @@ pub use generic_args::{GenericArgKind, TermKind, *};
pub use generics::*;
pub use intrinsic::IntrinsicDef;
use rustc_abi::{Align, FieldIdx, Integer, IntegerType, ReprFlags, ReprOptions, VariantIdx};
use rustc_ast::AttrVec;
use rustc_ast::expand::typetree::{FncTree, Kind, Type, TypeTree};
use rustc_ast::node_id::NodeMap;
pub use rustc_ast_ir::{Movability, Mutability, try_visit};
@ -221,13 +222,24 @@ pub struct ResolverAstLowering {
pub delegation_fn_sigs: LocalDefIdMap<DelegationFnSig>,
}
bitflags::bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct DelegationFnSigAttrs: u8 {
const TARGET_FEATURE = 1 << 0;
const MUST_USE = 1 << 1;
}
}
pub const DELEGATION_INHERIT_ATTRS_START: DelegationFnSigAttrs = DelegationFnSigAttrs::MUST_USE;
#[derive(Debug)]
pub struct DelegationFnSig {
pub header: ast::FnHeader,
pub param_count: usize,
pub has_self: bool,
pub c_variadic: bool,
pub target_feature: bool,
pub attrs_flags: DelegationFnSigAttrs,
pub to_inherit_attrs: AttrVec,
}
#[derive(Clone, Copy, Debug, HashStable)]
@ -2395,9 +2407,7 @@ fn typetree_from_ty_impl_inner<'tcx>(
}
if ty.is_ref() || ty.is_raw_ptr() || ty.is_box() {
let inner_ty = if let Some(inner) = ty.builtin_deref(true) {
inner
} else {
let Some(inner_ty) = ty.builtin_deref(true) else {
return TypeTree::new();
};

View file

@ -16,7 +16,7 @@ use rustc_hir::definitions::{DefKey, DefPathDataName};
use rustc_hir::limit::Limit;
use rustc_macros::{Lift, extension};
use rustc_session::cstore::{ExternCrate, ExternCrateSource};
use rustc_span::{FileNameDisplayPreference, Ident, Symbol, kw, sym};
use rustc_span::{Ident, RemapPathScopeComponents, Symbol, kw, sym};
use rustc_type_ir::{Upcast as _, elaborate};
use smallvec::SmallVec;
@ -890,7 +890,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
"@{}",
// This may end up in stderr diagnostics but it may also be emitted
// into MIR. Hence we use the remapped path if available
self.tcx().sess.source_map().span_to_embeddable_string(span)
self.tcx().sess.source_map().span_to_diagnostic_string(span)
)?;
} else {
write!(self, "@")?;
@ -921,7 +921,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
"@{}",
// This may end up in stderr diagnostics but it may also be emitted
// into MIR. Hence we use the remapped path if available
self.tcx().sess.source_map().span_to_embeddable_string(span)
self.tcx().sess.source_map().span_to_diagnostic_string(span)
)?;
} else {
write!(self, "@")?;
@ -947,10 +947,13 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
self.print_def_path(did.to_def_id(), args)?;
} else {
let span = self.tcx().def_span(did);
let preference = if with_forced_trimmed_paths() {
FileNameDisplayPreference::Short
let loc = if with_forced_trimmed_paths() {
self.tcx().sess.source_map().span_to_short_string(
span,
RemapPathScopeComponents::DIAGNOSTICS,
)
} else {
FileNameDisplayPreference::Remapped
self.tcx().sess.source_map().span_to_diagnostic_string(span)
};
write!(
self,
@ -958,7 +961,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
// This may end up in stderr diagnostics but it may also be
// emitted into MIR. Hence we use the remapped path if
// available
self.tcx().sess.source_map().span_to_string(span, preference)
loc
)?;
}
} else {
@ -1004,18 +1007,17 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
self.print_def_path(did.to_def_id(), args)?;
} else {
let span = self.tcx().def_span(did);
let preference = if with_forced_trimmed_paths() {
FileNameDisplayPreference::Short
// This may end up in stderr diagnostics but it may also be emitted
// into MIR. Hence we use the remapped path if available
let loc = if with_forced_trimmed_paths() {
self.tcx().sess.source_map().span_to_short_string(
span,
RemapPathScopeComponents::DIAGNOSTICS,
)
} else {
FileNameDisplayPreference::Remapped
self.tcx().sess.source_map().span_to_diagnostic_string(span)
};
write!(
self,
"@{}",
// This may end up in stderr diagnostics but it may also be emitted
// into MIR. Hence we use the remapped path if available
self.tcx().sess.source_map().span_to_string(span, preference)
)?;
write!(self, "@{loc}")?;
}
} else {
write!(self, "@")?;
@ -2258,7 +2260,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
"<impl at {}>",
// This may end up in stderr diagnostics but it may also be emitted
// into MIR. Hence we use the remapped path if available
self.tcx.sess.source_map().span_to_embeddable_string(span)
self.tcx.sess.source_map().span_to_diagnostic_string(span)
)?;
self.empty_path = false;

View file

@ -1528,18 +1528,13 @@ impl<'tcx> Ty<'tcx> {
let mut cor_ty = self;
let mut ty = cor_ty;
loop {
if let ty::Coroutine(def_id, args) = ty.kind() {
cor_ty = ty;
f(ty);
if tcx.is_async_drop_in_place_coroutine(*def_id) {
ty = args.first().unwrap().expect_ty();
continue;
} else {
return cor_ty;
}
} else {
let ty::Coroutine(def_id, args) = ty.kind() else { return cor_ty };
cor_ty = ty;
f(ty);
if !tcx.is_async_drop_in_place_coroutine(*def_id) {
return cor_ty;
}
ty = args.first().unwrap().expect_ty();
}
}

View file

@ -100,11 +100,8 @@ impl<'tcx> MovePath<'tcx> {
move_paths: &IndexSlice<MovePathIndex, MovePath<'_>>,
f: impl Fn(MovePathIndex) -> bool,
) -> Option<MovePathIndex> {
let mut todo = if let Some(child) = self.first_child {
vec![child]
} else {
return None;
};
let Some(child) = self.first_child else { return None };
let mut todo = vec![child];
while let Some(mpi) = todo.pop() {
if f(mpi) {
@ -331,11 +328,10 @@ impl<'tcx> MovePathLookup<'tcx> {
MoveSubPathResult::Stop => None,
};
if let Some(&subpath) = subpath {
result = subpath;
} else {
let Some(&subpath) = subpath else {
return LookupResult::Parent(Some(result));
}
};
result = subpath;
}
LookupResult::Exact(result)

View file

@ -721,11 +721,8 @@ impl<'tcx> Map<'tcx> {
// Enum variant fields and enum discriminants alias each another.
self.for_each_variant_sibling(index, sub, f);
}
if let Some(sub) = sub {
index = sub
} else {
return;
}
let Some(sub) = sub else { return };
index = sub;
}
self.for_each_value_inside(index, f);
}

View file

@ -590,31 +590,30 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
let fields =
fields.iter().map(|&f| self.eval_to_const(f)).collect::<Option<Vec<_>>>()?;
let variant = if ty.ty.is_enum() { Some(variant) } else { None };
if matches!(ty.backend_repr, BackendRepr::Scalar(..) | BackendRepr::ScalarPair(..))
{
let dest = self.ecx.allocate(ty, MemoryKind::Stack).discard_err()?;
let variant_dest = if let Some(variant) = variant {
self.ecx.project_downcast(&dest, variant).discard_err()?
} else {
dest.clone()
};
for (field_index, op) in fields.into_iter().enumerate() {
let field_dest = self
.ecx
.project_field(&variant_dest, FieldIdx::from_usize(field_index))
.discard_err()?;
self.ecx.copy_op(op, &field_dest).discard_err()?;
}
self.ecx
.write_discriminant(variant.unwrap_or(FIRST_VARIANT), &dest)
.discard_err()?;
self.ecx
.alloc_mark_immutable(dest.ptr().provenance.unwrap().alloc_id())
.discard_err()?;
dest.into()
} else {
let (BackendRepr::Scalar(..) | BackendRepr::ScalarPair(..)) = ty.backend_repr
else {
return None;
};
let dest = self.ecx.allocate(ty, MemoryKind::Stack).discard_err()?;
let variant_dest = if let Some(variant) = variant {
self.ecx.project_downcast(&dest, variant).discard_err()?
} else {
dest.clone()
};
for (field_index, op) in fields.into_iter().enumerate() {
let field_dest = self
.ecx
.project_field(&variant_dest, FieldIdx::from_usize(field_index))
.discard_err()?;
self.ecx.copy_op(op, &field_dest).discard_err()?;
}
self.ecx
.write_discriminant(variant.unwrap_or(FIRST_VARIANT), &dest)
.discard_err()?;
self.ecx
.alloc_mark_immutable(dest.ptr().provenance.unwrap().alloc_id())
.discard_err()?;
dest.into()
}
Union(active_field, field) => {
let field = self.eval_to_const(field)?;

View file

@ -410,14 +410,8 @@ impl<'tcx> Validator<'_, 'tcx> {
// In theory, any zero-sized value could be borrowed
// mutably without consequences. However, only &mut []
// is allowed right now.
if let ty::Array(_, len) = ty.kind() {
match len.try_to_target_usize(self.tcx) {
Some(0) => {}
_ => return Err(Unpromotable),
}
} else {
return Err(Unpromotable);
}
let ty::Array(_, len) = ty.kind() else { return Err(Unpromotable) };
let Some(0) = len.try_to_target_usize(self.tcx) else { return Err(Unpromotable) };
}
}

View file

@ -49,7 +49,7 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In
.unwrap_or_else(|e| format!("Failed {e:?}"));
let closure_span = tcx.def_span(closure_def_id);
let src_file = tcx.sess.source_map().span_to_filename(closure_span);
let src_file = tcx.sess.source_map().span_to_diagnostic_string(closure_span);
let line_nos = tcx
.sess
.source_map()
@ -57,14 +57,7 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In
.map(|l| format!("{:?} {:?}", l.lines.first(), l.lines.last()))
.unwrap_or_else(|e| format!("{e:?}"));
if let Err(e) = writeln!(
file,
"{}, {}, {}, {:?}",
old_size,
new_size,
src_file.prefer_local(),
line_nos
) {
if let Err(e) = writeln!(file, "{}, {}, {}, {:?}", old_size, new_size, src_file, line_nos) {
eprintln!("Error writing to file {e}")
}
}

View file

@ -445,17 +445,15 @@ where
goal_kind: ty::ClosureKind,
) -> Result<Candidate<I>, NoSolution> {
let cx = ecx.cx();
let tupled_inputs_and_output =
match structural_traits::extract_tupled_inputs_and_output_from_callable(
let Some(tupled_inputs_and_output) =
structural_traits::extract_tupled_inputs_and_output_from_callable(
cx,
goal.predicate.self_ty(),
goal_kind,
)? {
Some(tupled_inputs_and_output) => tupled_inputs_and_output,
None => {
return ecx.forced_ambiguity(MaybeCause::Ambiguity);
}
};
)?
else {
return ecx.forced_ambiguity(MaybeCause::Ambiguity);
};
let (inputs, output) = ecx.instantiate_binder_with_infer(tupled_inputs_and_output);
// A built-in `Fn` impl only holds if the output is sized.

View file

@ -360,17 +360,15 @@ where
}
let cx = ecx.cx();
let tupled_inputs_and_output =
match structural_traits::extract_tupled_inputs_and_output_from_callable(
let Some(tupled_inputs_and_output) =
structural_traits::extract_tupled_inputs_and_output_from_callable(
cx,
goal.predicate.self_ty(),
goal_kind,
)? {
Some(a) => a,
None => {
return ecx.forced_ambiguity(MaybeCause::Ambiguity);
}
};
)?
else {
return ecx.forced_ambiguity(MaybeCause::Ambiguity);
};
let (inputs, output) = ecx.instantiate_binder_with_infer(tupled_inputs_and_output);
// A built-in `Fn` impl only holds if the output is sized.
@ -1409,42 +1407,39 @@ where
let where_bounds: Vec<_> = candidates
.extract_if(.., |c| matches!(c.source, CandidateSource::ParamEnv(_)))
.collect();
if let Some((response, info)) = self.try_merge_candidates(&where_bounds) {
match info {
// If there's an always applicable candidate, the result of all
// other candidates does not matter. This means we can ignore
// them when checking whether we've reached a fixpoint.
//
// We always prefer the first always applicable candidate, even if a
// later candidate is also always applicable and would result in fewer
// reruns. We could slightly improve this by e.g. searching for another
// always applicable candidate which doesn't depend on any cycle heads.
//
// NOTE: This is optimization is observable in case there is an always
// applicable global candidate and another non-global candidate which only
// applies because of a provisional result. I can't even think of a test
// case where this would occur and even then, this would not be unsound.
// Supporting this makes the code more involved, so I am just going to
// ignore this for now.
MergeCandidateInfo::AlwaysApplicable(i) => {
for (j, c) in where_bounds.into_iter().enumerate() {
if i != j {
self.ignore_candidate_head_usages(c.head_usages)
}
}
// If a where-bound does not apply, we don't actually get a
// candidate for it. We manually track the head usages
// of all failed `ParamEnv` candidates instead.
self.ignore_candidate_head_usages(
failed_candidate_info.param_env_head_usages,
);
}
MergeCandidateInfo::EqualResponse => {}
}
return Ok((response, Some(TraitGoalProvenVia::ParamEnv)));
} else {
let Some((response, info)) = self.try_merge_candidates(&where_bounds) else {
return Ok((self.bail_with_ambiguity(&where_bounds), None));
};
match info {
// If there's an always applicable candidate, the result of all
// other candidates does not matter. This means we can ignore
// them when checking whether we've reached a fixpoint.
//
// We always prefer the first always applicable candidate, even if a
// later candidate is also always applicable and would result in fewer
// reruns. We could slightly improve this by e.g. searching for another
// always applicable candidate which doesn't depend on any cycle heads.
//
// NOTE: This is optimization is observable in case there is an always
// applicable global candidate and another non-global candidate which only
// applies because of a provisional result. I can't even think of a test
// case where this would occur and even then, this would not be unsound.
// Supporting this makes the code more involved, so I am just going to
// ignore this for now.
MergeCandidateInfo::AlwaysApplicable(i) => {
for (j, c) in where_bounds.into_iter().enumerate() {
if i != j {
self.ignore_candidate_head_usages(c.head_usages)
}
}
// If a where-bound does not apply, we don't actually get a
// candidate for it. We manually track the head usages
// of all failed `ParamEnv` candidates instead.
self.ignore_candidate_head_usages(failed_candidate_info.param_env_head_usages);
}
MergeCandidateInfo::EqualResponse => {}
}
return Ok((response, Some(TraitGoalProvenVia::ParamEnv)));
}
// Next, prefer any alias bound (nested or otherwise).

View file

@ -316,7 +316,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
// Include the leading `'` in the real identifier, for macro
// expansion purposes. See #12512 for the gory details of why
// this is necessary.
let lifetime_name = self.str_from(start);
let lifetime_name = nfc_normalize(self.str_from(start));
self.last_lifetime = Some(self.mk_sp(start, start + BytePos(1)));
if starts_with_number {
let span = self.mk_sp(start, self.pos);
@ -325,8 +325,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
.with_span(span)
.stash(span, StashKey::LifetimeIsChar);
}
let ident = Symbol::intern(lifetime_name);
token::Lifetime(ident, IdentIsRaw::No)
token::Lifetime(lifetime_name, IdentIsRaw::No)
}
rustc_lexer::TokenKind::RawLifetime => {
self.last_lifetime = Some(self.mk_sp(start, start + BytePos(1)));
@ -373,7 +372,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
String::with_capacity(lifetime_name_without_tick.as_str().len() + 1);
lifetime_name.push('\'');
lifetime_name += lifetime_name_without_tick.as_str();
let sym = Symbol::intern(&lifetime_name);
let sym = nfc_normalize(&lifetime_name);
// Make sure we mark this as a raw identifier.
self.psess.raw_identifier_spans.push(span);
@ -393,9 +392,8 @@ impl<'psess, 'src> Lexer<'psess, 'src> {
self.pos = lt_start;
self.cursor = Cursor::new(&str_before[2 as usize..], FrontmatterAllowed::No);
let lifetime_name = self.str_from(start);
let ident = Symbol::intern(lifetime_name);
token::Lifetime(ident, IdentIsRaw::No)
let lifetime_name = nfc_normalize(self.str_from(start));
token::Lifetime(lifetime_name, IdentIsRaw::No)
}
}
rustc_lexer::TokenKind::Semi => token::Semi,

View file

@ -129,7 +129,13 @@ pub fn utf8_error<E: EmissionGuarantee>(
note.clone()
};
let contents = String::from_utf8_lossy(contents).to_string();
let source = sm.new_source_file(PathBuf::from(path).into(), contents);
// We only emit this error for files in the current session
// so the working directory can only be the current working directory
let filename = FileName::Real(
sm.path_mapping().to_real_filename(sm.working_dir(), PathBuf::from(path).as_path()),
);
let source = sm.new_source_file(filename, contents);
// Avoid out-of-bounds span from lossy UTF-8 conversion.
if start as u32 > source.normalized_source_len.0 {

View file

@ -2,7 +2,7 @@
use std::assert_matches::assert_matches;
use std::io::prelude::*;
use std::iter::Peekable;
use std::path::{Path, PathBuf};
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
use std::{io, str};
@ -29,11 +29,15 @@ fn psess() -> ParseSess {
ParseSess::new(vec![crate::DEFAULT_LOCALE_RESOURCE])
}
fn filename(sm: &SourceMap, path: &str) -> FileName {
FileName::Real(sm.path_mapping().to_real_filename(sm.working_dir(), PathBuf::from(path)))
}
/// Map string to parser (via tts).
fn string_to_parser(psess: &ParseSess, source_str: String) -> Parser<'_> {
unwrap_or_emit_fatal(new_parser_from_source_str(
psess,
PathBuf::from("bogofile").into(),
filename(psess.source_map(), "bogofile"),
source_str,
StripTokens::Nothing,
))
@ -100,7 +104,7 @@ pub(crate) fn string_to_stream(source_str: String) -> TokenStream {
let psess = psess();
unwrap_or_emit_fatal(source_str_to_stream(
&psess,
PathBuf::from("bogofile").into(),
filename(psess.source_map(), "bogofile"),
source_str,
None,
))
@ -194,8 +198,7 @@ fn test_harness(
(OutputTheme::Unicode, expected_output_unicode),
] {
let (dcx, source_map, output) = create_test_handler(theme);
source_map
.new_source_file(Path::new("test.rs").to_owned().into(), file_text.to_owned());
source_map.new_source_file(filename(&source_map, "test.rs"), file_text.to_owned());
let primary_span = make_span(&file_text, &span_labels[0].start, &span_labels[0].end);
let mut msp = MultiSpan::from_span(primary_span);
@ -2525,7 +2528,7 @@ fn ttdelim_span() {
create_default_session_globals_then(|| {
let psess = psess();
let expr = parse_expr_from_source_str(
PathBuf::from("foo").into(),
filename(psess.source_map(), "foo"),
"foo!( fn main() { body } )".to_string(),
&psess,
)
@ -2888,10 +2891,11 @@ fn debug_lookahead() {
#[test]
fn out_of_line_mod() {
create_default_session_globals_then(|| {
let psess = psess();
let item = parse_item_from_source_str(
PathBuf::from("foo").into(),
filename(psess.source_map(), "foo"),
"mod foo { struct S; mod this_does_not_exist; }".to_owned(),
&psess(),
&psess,
)
.unwrap()
.unwrap();

View file

@ -6,9 +6,8 @@ use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE, LocalDefId};
use rustc_hir::{CRATE_HIR_ID, ItemId, Node, find_attr};
use rustc_middle::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::RemapFileNameExt;
use rustc_session::config::{CrateType, EntryFnType, RemapPathScopeComponents, sigpipe};
use rustc_span::{Span, sym};
use rustc_session::config::{CrateType, EntryFnType, sigpipe};
use rustc_span::{RemapPathScopeComponents, Span, sym};
use crate::errors::{ExternMain, MultipleRustcMain, NoMainErr};
@ -115,7 +114,7 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) {
let filename = tcx
.sess
.local_crate_source_file()
.map(|src| src.for_scope(&tcx.sess, RemapPathScopeComponents::DIAGNOSTICS).to_path_buf())
.map(|src| src.path(RemapPathScopeComponents::DIAGNOSTICS).to_path_buf())
.unwrap_or_else(|| {
has_filename = false;
Default::default()

View file

@ -23,7 +23,7 @@ use rustc_middle::ty::{
use rustc_middle::{mir, ty};
use rustc_session::cstore::ForeignModule;
use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc_span::{FileNameDisplayPreference, Span, Symbol};
use rustc_span::{Span, Symbol};
use rustc_target::callconv::FnAbi;
use super::{AllocRangeHelpers, CompilerCtxt, TyHelpers, TypingEnvHelpers};
@ -324,12 +324,7 @@ impl<'tcx, B: Bridge> CompilerCtxt<'tcx, B> {
/// Return filename from given `Span`, for diagnostic purposes.
pub fn get_filename(&self, span: Span) -> String {
self.tcx
.sess
.source_map()
.span_to_filename(span)
.display(FileNameDisplayPreference::Local)
.to_string()
self.tcx.sess.source_map().span_to_filename(span).prefer_local_unconditionally().to_string()
}
/// Return lines corresponding to this `Span`.

View file

@ -1363,7 +1363,10 @@ impl DepNodeColorMap {
Ordering::Relaxed,
) {
Ok(_) => Ok(()),
Err(v) => Err(DepNodeIndex::from_u32(v)),
Err(v) => Err({
assert_ne!(v, COMPRESSED_RED, "tried to mark a red node as green");
DepNodeIndex::from_u32(v)
}),
}
}
@ -1384,7 +1387,9 @@ impl DepNodeColorMap {
#[inline]
pub(super) fn insert_red(&self, index: SerializedDepNodeIndex) {
self.values[index].store(COMPRESSED_RED, Ordering::Release)
let value = self.values[index].swap(COMPRESSED_RED, Ordering::Release);
// Sanity check for duplicate nodes
assert_eq!(value, COMPRESSED_UNKNOWN, "trying to encode a dep node twice");
}
}

View file

@ -771,36 +771,39 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
} else {
None
};
// Skip ambiguity errors for extern flag bindings "overridden"
// by extern item bindings.
// FIXME: Remove with lang team approval.
let issue_145575_hack = Some(binding) == extern_prelude_flag_binding
&& extern_prelude_item_binding.is_some()
&& extern_prelude_item_binding != Some(innermost_binding);
if let Some(kind) = ambiguity_error_kind
&& !issue_145575_hack
{
let misc = |f: Flags| {
if f.contains(Flags::MISC_SUGGEST_CRATE) {
AmbiguityErrorMisc::SuggestCrate
} else if f.contains(Flags::MISC_SUGGEST_SELF) {
AmbiguityErrorMisc::SuggestSelf
} else if f.contains(Flags::MISC_FROM_PRELUDE) {
AmbiguityErrorMisc::FromPrelude
} else {
AmbiguityErrorMisc::None
}
};
self.ambiguity_errors.push(AmbiguityError {
kind,
ident: orig_ident,
b1: innermost_binding,
b2: binding,
warning: false,
misc1: misc(innermost_flags),
misc2: misc(flags),
});
return true;
if let Some(kind) = ambiguity_error_kind {
// Skip ambiguity errors for extern flag bindings "overridden"
// by extern item bindings.
// FIXME: Remove with lang team approval.
let issue_145575_hack = Some(binding) == extern_prelude_flag_binding
&& extern_prelude_item_binding.is_some()
&& extern_prelude_item_binding != Some(innermost_binding);
if issue_145575_hack {
self.issue_145575_hack_applied = true;
} else {
let misc = |f: Flags| {
if f.contains(Flags::MISC_SUGGEST_CRATE) {
AmbiguityErrorMisc::SuggestCrate
} else if f.contains(Flags::MISC_SUGGEST_SELF) {
AmbiguityErrorMisc::SuggestSelf
} else if f.contains(Flags::MISC_FROM_PRELUDE) {
AmbiguityErrorMisc::FromPrelude
} else {
AmbiguityErrorMisc::None
}
};
self.ambiguity_errors.push(AmbiguityError {
kind,
ident: orig_ident,
b1: innermost_binding,
b2: binding,
warning: false,
misc1: misc(innermost_flags),
misc2: misc(flags),
});
return true;
}
}
false

View file

@ -1170,7 +1170,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
return;
}
if let Some(initial_res) = initial_res {
if res != initial_res {
if res != initial_res && !this.issue_145575_hack_applied {
span_bug!(import.span, "inconsistent resolution for an import");
}
} else if this.privacy_errors.is_empty() {

View file

@ -28,7 +28,9 @@ use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, Par
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE, LocalDefId};
use rustc_hir::{MissingLifetimeKind, PrimTy, TraitCandidate};
use rustc_middle::middle::resolve_bound_vars::Set1;
use rustc_middle::ty::{AssocTag, DelegationFnSig, Visibility};
use rustc_middle::ty::{
AssocTag, DELEGATION_INHERIT_ATTRS_START, DelegationFnSig, DelegationFnSigAttrs, Visibility,
};
use rustc_middle::{bug, span_bug};
use rustc_session::config::{CrateType, ResolveDocLinks};
use rustc_session::lint;
@ -5297,13 +5299,37 @@ impl ItemInfoCollector<'_, '_, '_> {
id: NodeId,
attrs: &[Attribute],
) {
static NAMES_TO_FLAGS: &[(Symbol, DelegationFnSigAttrs)] = &[
(sym::target_feature, DelegationFnSigAttrs::TARGET_FEATURE),
(sym::must_use, DelegationFnSigAttrs::MUST_USE),
];
let mut to_inherit_attrs = AttrVec::new();
let mut attrs_flags = DelegationFnSigAttrs::empty();
'attrs_loop: for attr in attrs {
for &(name, flag) in NAMES_TO_FLAGS {
if attr.has_name(name) {
attrs_flags.set(flag, true);
if flag.bits() >= DELEGATION_INHERIT_ATTRS_START.bits() {
to_inherit_attrs.push(attr.clone());
}
continue 'attrs_loop;
}
}
}
let sig = DelegationFnSig {
header,
param_count: decl.inputs.len(),
has_self: decl.has_self(),
c_variadic: decl.c_variadic(),
target_feature: attrs.iter().any(|attr| attr.has_name(sym::target_feature)),
attrs_flags,
to_inherit_attrs,
};
self.r.delegation_fn_sigs.insert(self.r.local_def_id(id), sig);
}
}

View file

@ -1537,86 +1537,80 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
/// Given `where <T as Bar>::Baz: String`, suggest `where T: Bar<Baz = String>`.
fn restrict_assoc_type_in_where_clause(&self, span: Span, err: &mut Diag<'_>) -> bool {
// Detect that we are actually in a `where` predicate.
let (bounded_ty, bounds, where_span) = if let Some(ast::WherePredicate {
let Some(ast::WherePredicate {
kind:
ast::WherePredicateKind::BoundPredicate(ast::WhereBoundPredicate {
bounded_ty,
bound_generic_params,
bounds,
}),
span,
span: where_span,
..
}) = self.diag_metadata.current_where_predicate
{
if !bound_generic_params.is_empty() {
return false;
}
(bounded_ty, bounds, span)
} else {
else {
return false;
};
if !bound_generic_params.is_empty() {
return false;
}
// Confirm that the target is an associated type.
let (ty, _, path) = if let ast::TyKind::Path(Some(qself), path) = &bounded_ty.kind {
// use this to verify that ident is a type param.
let Some(partial_res) = self.r.partial_res_map.get(&bounded_ty.id) else {
return false;
};
if !matches!(
partial_res.full_res(),
Some(hir::def::Res::Def(hir::def::DefKind::AssocTy, _))
) {
return false;
}
(&qself.ty, qself.position, path)
} else {
let ast::TyKind::Path(Some(qself), path) = &bounded_ty.kind else { return false };
// use this to verify that ident is a type param.
let Some(partial_res) = self.r.partial_res_map.get(&bounded_ty.id) else { return false };
if !matches!(
partial_res.full_res(),
Some(hir::def::Res::Def(hir::def::DefKind::AssocTy, _))
) {
return false;
}
let peeled_ty = qself.ty.peel_refs();
let ast::TyKind::Path(None, type_param_path) = &peeled_ty.kind else { return false };
// Confirm that the `SelfTy` is a type parameter.
let Some(partial_res) = self.r.partial_res_map.get(&peeled_ty.id) else {
return false;
};
let peeled_ty = ty.peel_refs();
if let ast::TyKind::Path(None, type_param_path) = &peeled_ty.kind {
// Confirm that the `SelfTy` is a type parameter.
let Some(partial_res) = self.r.partial_res_map.get(&peeled_ty.id) else {
if !matches!(
partial_res.full_res(),
Some(hir::def::Res::Def(hir::def::DefKind::TyParam, _))
) {
return false;
}
let ([ast::PathSegment { args: None, .. }], [ast::GenericBound::Trait(poly_trait_ref)]) =
(&type_param_path.segments[..], &bounds[..])
else {
return false;
};
let [ast::PathSegment { ident, args: None, id }] =
&poly_trait_ref.trait_ref.path.segments[..]
else {
return false;
};
if poly_trait_ref.modifiers != ast::TraitBoundModifiers::NONE {
return false;
}
if ident.span == span {
let Some(partial_res) = self.r.partial_res_map.get(&id) else {
return false;
};
if !matches!(
partial_res.full_res(),
Some(hir::def::Res::Def(hir::def::DefKind::TyParam, _))
) {
if !matches!(partial_res.full_res(), Some(hir::def::Res::Def(..))) {
return false;
}
if let (
[ast::PathSegment { args: None, .. }],
[ast::GenericBound::Trait(poly_trait_ref)],
) = (&type_param_path.segments[..], &bounds[..])
&& let [ast::PathSegment { ident, args: None, id }] =
&poly_trait_ref.trait_ref.path.segments[..]
&& poly_trait_ref.modifiers == ast::TraitBoundModifiers::NONE
{
if ident.span == span {
let Some(partial_res) = self.r.partial_res_map.get(&id) else {
return false;
};
if !matches!(partial_res.full_res(), Some(hir::def::Res::Def(..))) {
return false;
}
let Some(new_where_bound_predicate) =
mk_where_bound_predicate(path, poly_trait_ref, ty)
else {
return false;
};
err.span_suggestion_verbose(
*where_span,
format!("constrain the associated type to `{ident}`"),
where_bound_predicate_to_string(&new_where_bound_predicate),
Applicability::MaybeIncorrect,
);
}
return true;
}
let Some(new_where_bound_predicate) =
mk_where_bound_predicate(path, poly_trait_ref, &qself.ty)
else {
return false;
};
err.span_suggestion_verbose(
*where_span,
format!("constrain the associated type to `{ident}`"),
where_bound_predicate_to_string(&new_where_bound_predicate),
Applicability::MaybeIncorrect,
);
}
false
true
}
/// Check if the source is call expression and the first argument is `self`. If true,

View file

@ -10,6 +10,7 @@
#![allow(internal_features)]
#![allow(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::untranslatable_diagnostic)]
#![deny(clippy::manual_let_else)]
#![feature(arbitrary_self_types)]
#![feature(assert_matches)]
#![feature(box_patterns)]
@ -1187,6 +1188,7 @@ pub struct Resolver<'ra, 'tcx> {
privacy_errors: Vec<PrivacyError<'ra>> = Vec::new(),
/// Ambiguity errors are delayed for deduplication.
ambiguity_errors: Vec<AmbiguityError<'ra>> = Vec::new(),
issue_145575_hack_applied: bool = false,
/// `use` injections are delayed for better placement and deduplication.
use_injections: Vec<UseError<'tcx>> = Vec::new(),
/// Crate-local macro expanded `macro_export` referred to by a module-relative path.

View file

@ -2,14 +2,18 @@ use std::path::PathBuf;
use rustc_span::source_map::{FilePathMapping, SourceMap};
use rustc_span::symbol::sym;
use rustc_span::{BytePos, DUMMY_SP, Span};
use rustc_span::{BytePos, DUMMY_SP, FileName, Span};
use super::{DocFragment, DocFragmentKind, source_span_for_markdown_range_inner};
fn filename(sm: &SourceMap, path: &str) -> FileName {
FileName::Real(sm.path_mapping().to_real_filename(sm.working_dir(), PathBuf::from(path)))
}
#[test]
fn single_backtick() {
let sm = SourceMap::new(FilePathMapping::empty());
sm.new_source_file(PathBuf::from("foo.rs").into(), r#"#[doc = "`"] fn foo() {}"#.to_string());
sm.new_source_file(filename(&sm, "foo.rs"), r#"#[doc = "`"] fn foo() {}"#.to_string());
let (span, _) = source_span_for_markdown_range_inner(
&sm,
"`",
@ -32,7 +36,7 @@ fn single_backtick() {
fn utf8() {
// regression test for https://github.com/rust-lang/rust/issues/141665
let sm = SourceMap::new(FilePathMapping::empty());
sm.new_source_file(PathBuf::from("foo.rs").into(), r#"#[doc = "⚠"] fn foo() {}"#.to_string());
sm.new_source_file(filename(&sm, "foo.rs"), r#"#[doc = "⚠"] fn foo() {}"#.to_string());
let (span, _) = source_span_for_markdown_range_inner(
&sm,
"",

View file

@ -5,7 +5,6 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
bitflags = "2.4.1"
getopts = "0.2"
rand = "0.9.0"
rustc_abi = { path = "../rustc_abi" }

View file

@ -24,10 +24,7 @@ use rustc_hashes::Hash64;
use rustc_macros::{BlobDecodable, Decodable, Encodable, HashStable_Generic};
use rustc_span::edition::{DEFAULT_EDITION, EDITION_NAME_LIST, Edition, LATEST_STABLE_EDITION};
use rustc_span::source_map::FilePathMapping;
use rustc_span::{
FileName, FileNameDisplayPreference, FileNameEmbeddablePreference, RealFileName,
SourceFileHashAlgorithm, Symbol, sym,
};
use rustc_span::{FileName, RealFileName, SourceFileHashAlgorithm, Symbol, sym};
use rustc_target::spec::{
FramePointer, LinkSelfContainedComponents, LinkerFeatures, PanicStrategy, SplitDebuginfo,
Target, TargetTuple,
@ -1022,9 +1019,15 @@ impl Input {
"rust_out"
}
pub fn source_name(&self) -> FileName {
pub fn file_name(&self, session: &Session) -> FileName {
match *self {
Input::File(ref ifile) => ifile.clone().into(),
Input::File(ref ifile) => FileName::Real(
session
.psess
.source_map()
.path_mapping()
.to_real_filename(session.psess.source_map().working_dir(), ifile.as_path()),
),
Input::Str { ref name, .. } => name.clone(),
}
}
@ -1312,25 +1315,6 @@ impl OutputFilenames {
}
}
bitflags::bitflags! {
/// Scopes used to determined if it need to apply to --remap-path-prefix
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct RemapPathScopeComponents: u8 {
/// Apply remappings to the expansion of std::file!() macro
const MACRO = 1 << 0;
/// Apply remappings to printed compiler diagnostics
const DIAGNOSTICS = 1 << 1;
/// Apply remappings to debug information
const DEBUGINFO = 1 << 3;
/// Apply remappings to coverage information
const COVERAGE = 1 << 4;
/// An alias for `macro`, `debuginfo` and `coverage`. This ensures all paths in compiled
/// executables, libraries and objects are remapped but not elsewhere.
const OBJECT = Self::MACRO.bits() | Self::DEBUGINFO.bits() | Self::COVERAGE.bits();
}
}
#[derive(Clone, Debug)]
pub struct Sysroot {
pub explicit: Option<PathBuf>,
@ -1369,25 +1353,22 @@ fn file_path_mapping(
remap_path_prefix: Vec<(PathBuf, PathBuf)>,
unstable_opts: &UnstableOptions,
) -> FilePathMapping {
FilePathMapping::new(
remap_path_prefix.clone(),
if unstable_opts.remap_path_scope.contains(RemapPathScopeComponents::DIAGNOSTICS)
&& !remap_path_prefix.is_empty()
{
FileNameDisplayPreference::Remapped
} else {
FileNameDisplayPreference::Local
},
if unstable_opts.remap_path_scope.is_all() {
FileNameEmbeddablePreference::RemappedOnly
} else {
FileNameEmbeddablePreference::LocalAndRemapped
},
)
FilePathMapping::new(remap_path_prefix.clone(), unstable_opts.remap_path_scope)
}
impl Default for Options {
fn default() -> Options {
let unstable_opts = UnstableOptions::default();
// FIXME(Urgau): This is a hack that ideally shouldn't exist, but rustdoc
// currently uses this `Default` implementation, so we have no choice but
// to create a default working directory.
let working_dir = {
let working_dir = std::env::current_dir().unwrap();
let file_mapping = file_path_mapping(Vec::new(), &unstable_opts);
file_mapping.to_real_filename(&RealFileName::empty(), &working_dir)
};
Options {
assert_incr_state: None,
crate_types: Vec::new(),
@ -1404,7 +1385,7 @@ impl Default for Options {
test: false,
incremental: None,
untracked_state_hash: Default::default(),
unstable_opts: Default::default(),
unstable_opts,
prints: Vec::new(),
cg: Default::default(),
error_format: ErrorOutputType::default(),
@ -1428,7 +1409,7 @@ impl Default for Options {
json_unused_externs: JsonUnusedExterns::No,
json_future_incompat: false,
pretty: None,
working_dir: RealFileName::LocalPath(std::env::current_dir().unwrap()),
working_dir,
color: ColorConfig::Auto,
logical_env: FxIndexMap::default(),
verbose: false,
@ -2782,12 +2763,16 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
.collect()
};
let working_dir = std::env::current_dir().unwrap_or_else(|e| {
early_dcx.early_fatal(format!("Current directory is invalid: {e}"));
});
// Ideally we would use `SourceMap::working_dir` instead, but we don't have access to it
// so we manually create the potentially-remapped working directory
let working_dir = {
let working_dir = std::env::current_dir().unwrap_or_else(|e| {
early_dcx.early_fatal(format!("Current directory is invalid: {e}"));
});
let file_mapping = file_path_mapping(remap_path_prefix.clone(), &unstable_opts);
let working_dir = file_mapping.to_real_filename(&working_dir);
let file_mapping = file_path_mapping(remap_path_prefix.clone(), &unstable_opts);
file_mapping.to_real_filename(&RealFileName::empty(), &working_dir)
};
let verbose = matches.opt_present("verbose") || unstable_opts.verbose_internals;
@ -3115,8 +3100,8 @@ pub(crate) mod dep_tracking {
use rustc_errors::LanguageIdentifier;
use rustc_feature::UnstableFeatures;
use rustc_hashes::Hash64;
use rustc_span::RealFileName;
use rustc_span::edition::Edition;
use rustc_span::{RealFileName, RemapPathScopeComponents};
use rustc_target::spec::{
CodeModel, FramePointer, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel,
RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, SymbolVisibility, TargetTuple,
@ -3128,9 +3113,9 @@ pub(crate) mod dep_tracking {
CoverageOptions, CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FmtDebug,
FunctionReturn, InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto,
LocationDetail, LtoCli, MirStripDebugInfo, NextSolverConfig, Offload, OptLevel,
OutFileName, OutputType, OutputTypes, PatchableFunctionEntry, Polonius,
RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind,
SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
OutFileName, OutputType, OutputTypes, PatchableFunctionEntry, Polonius, ResolveDocLinks,
SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion,
WasiExecModel,
};
use crate::lint;
use crate::utils::NativeLib;

View file

@ -12,7 +12,7 @@ use rustc_feature::UnstableFeatures;
use rustc_hashes::Hash64;
use rustc_macros::{BlobDecodable, Encodable};
use rustc_span::edition::Edition;
use rustc_span::{RealFileName, SourceFileHashAlgorithm};
use rustc_span::{RealFileName, RemapPathScopeComponents, SourceFileHashAlgorithm};
use rustc_target::spec::{
CodeModel, FramePointer, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy,
RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, SymbolVisibility,
@ -492,7 +492,9 @@ top_level_options!(
pretty: Option<PpMode> [UNTRACKED],
/// The (potentially remapped) working directory
#[rustc_lint_opt_deny_field_access("use `SourceMap::working_dir` instead of this field")]
working_dir: RealFileName [TRACKED],
color: ColorConfig [UNTRACKED],
verbose: bool [TRACKED_NO_CRATE_HASH],

View file

@ -1,5 +1,5 @@
use std::any::Any;
use std::path::{Path, PathBuf};
use std::path::PathBuf;
use std::str::FromStr;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
@ -28,7 +28,7 @@ use rustc_macros::HashStable_Generic;
pub use rustc_span::def_id::StableCrateId;
use rustc_span::edition::Edition;
use rustc_span::source_map::{FilePathMapping, SourceMap};
use rustc_span::{FileNameDisplayPreference, RealFileName, Span, Symbol};
use rustc_span::{RealFileName, Span, Symbol};
use rustc_target::asm::InlineAsmArch;
use rustc_target::spec::{
Arch, CodeModel, DebuginfoKind, Os, PanicStrategy, RelocModel, RelroLevel, SanitizerSet,
@ -40,8 +40,7 @@ use crate::code_stats::CodeStats;
pub use crate::code_stats::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
use crate::config::{
self, CoverageLevel, CoverageOptions, CrateType, DebugInfo, ErrorOutputType, FunctionReturn,
Input, InstrumentCoverage, OptLevel, OutFileName, OutputType, RemapPathScopeComponents,
SwitchWithOptPath,
Input, InstrumentCoverage, OptLevel, OutFileName, OutputType, SwitchWithOptPath,
};
use crate::filesearch::FileSearch;
use crate::lint::LintId;
@ -192,7 +191,11 @@ impl Session {
}
pub fn local_crate_source_file(&self) -> Option<RealFileName> {
Some(self.source_map().path_mapping().to_real_filename(self.io.input.opt_path()?))
Some(
self.source_map()
.path_mapping()
.to_real_filename(self.source_map().working_dir(), self.io.input.opt_path()?),
)
}
fn check_miri_unleashed_features(&self) -> Option<ErrorGuaranteed> {
@ -846,21 +849,6 @@ impl Session {
self.opts.cg.link_dead_code.unwrap_or(false)
}
pub fn filename_display_preference(
&self,
scope: RemapPathScopeComponents,
) -> FileNameDisplayPreference {
assert!(
scope.bits().count_ones() == 1,
"one and only one scope should be passed to `Session::filename_display_preference`"
);
if self.opts.unstable_opts.remap_path_scope.contains(scope) {
FileNameDisplayPreference::Remapped
} else {
FileNameDisplayPreference::Local
}
}
/// Get the deployment target on Apple platforms based on the standard environment variables,
/// or fall back to the minimum version supported by `rustc`.
///
@ -1496,46 +1484,3 @@ fn mk_emitter(output: ErrorOutputType) -> Box<DynEmitter> {
};
emitter
}
pub trait RemapFileNameExt {
type Output<'a>
where
Self: 'a;
/// Returns a possibly remapped filename based on the passed scope and remap cli options.
///
/// One and only one scope should be passed to this method, it will panic otherwise.
fn for_scope(&self, sess: &Session, scope: RemapPathScopeComponents) -> Self::Output<'_>;
}
impl RemapFileNameExt for rustc_span::FileName {
type Output<'a> = rustc_span::FileNameDisplay<'a>;
fn for_scope(&self, sess: &Session, scope: RemapPathScopeComponents) -> Self::Output<'_> {
assert!(
scope.bits().count_ones() == 1,
"one and only one scope should be passed to for_scope"
);
if sess.opts.unstable_opts.remap_path_scope.contains(scope) {
self.prefer_remapped_unconditionally()
} else {
self.prefer_local()
}
}
}
impl RemapFileNameExt for rustc_span::RealFileName {
type Output<'a> = &'a Path;
fn for_scope(&self, sess: &Session, scope: RemapPathScopeComponents) -> Self::Output<'_> {
assert!(
scope.bits().count_ones() == 1,
"one and only one scope should be passed to for_scope"
);
if sess.opts.unstable_opts.remap_path_scope.contains(scope) {
self.remapped_path_if_available()
} else {
self.local_path_if_available()
}
}
}

View file

@ -5,6 +5,7 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
bitflags = "2.4.1"
blake3 = "1.5.2"
derive-where = "1.2.7"
indexmap = { version = "2.0.0" }

View file

@ -221,99 +221,227 @@ pub fn with_metavar_spans<R>(f: impl FnOnce(&MetavarSpansMap) -> R) -> R {
with_session_globals(|session_globals| f(&session_globals.metavar_spans))
}
// FIXME: We should use this enum or something like it to get rid of the
// use of magic `/rust/1.x/...` paths across the board.
bitflags::bitflags! {
/// Scopes used to determined if it need to apply to `--remap-path-prefix`
#[derive(Debug, Eq, PartialEq, Clone, Copy, Ord, PartialOrd, Hash)]
pub struct RemapPathScopeComponents: u8 {
/// Apply remappings to the expansion of `std::file!()` macro
const MACRO = 1 << 0;
/// Apply remappings to printed compiler diagnostics
const DIAGNOSTICS = 1 << 1;
/// Apply remappings to debug information
const DEBUGINFO = 1 << 3;
/// Apply remappings to coverage information
const COVERAGE = 1 << 4;
/// An alias for `macro`, `debuginfo` and `coverage`. This ensures all paths in compiled
/// executables, libraries and objects are remapped but not elsewhere.
const OBJECT = Self::MACRO.bits() | Self::DEBUGINFO.bits() | Self::COVERAGE.bits();
}
}
impl<E: Encoder> Encodable<E> for RemapPathScopeComponents {
fn encode(&self, s: &mut E) {
s.emit_u8(self.bits());
}
}
impl<D: Decoder> Decodable<D> for RemapPathScopeComponents {
fn decode(s: &mut D) -> RemapPathScopeComponents {
RemapPathScopeComponents::from_bits(s.read_u8())
.expect("invalid bits for RemapPathScopeComponents")
}
}
/// A self-contained "real" filename.
///
/// It is produced by `SourceMap::to_real_filename`.
///
/// `RealFileName` represents a filename that may have been (partly) remapped
/// by `--remap-path-prefix` and `-Zremap-path-scope`.
///
/// It also contains an embedabble component which gives a working directory
/// and a maybe-remapped maybe-aboslote name. This is useful for debuginfo where
/// some formats and tools highly prefer absolute paths.
///
/// ## Consistency across compiler sessions
///
/// The type-system, const-eval and other parts of the compiler rely on `FileName`
/// and by extension `RealFileName` to be consistent across compiler sessions.
///
/// Otherwise unsoudness (like rust-lang/rust#148328) may occur.
///
/// As such this type is self-sufficient and consistent in it's output.
///
/// The [`RealFileName::path`] and [`RealFileName::embeddable_name`] methods
/// are guaranteed to always return the same output across compiler sessions.
///
/// ## Usage
///
/// Creation of a [`RealFileName`] should be done using
/// [`FilePathMapping::to_real_filename`][rustc_span::source_map::FilePathMapping::to_real_filename].
///
/// Retrieving a path can be done in two main ways:
/// - by using [`RealFileName::path`] with a given scope (should be preferred)
/// - or by using [`RealFileName::embeddable_name`] with a given scope
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Decodable, Encodable)]
pub enum RealFileName {
LocalPath(PathBuf),
/// For remapped paths (namely paths into libstd that have been mapped
/// to the appropriate spot on the local host's file system, and local file
/// system paths that have been remapped with `FilePathMapping`),
Remapped {
/// `local_path` is the (host-dependent) local path to the file. This is
/// None if the file was imported from another crate
local_path: Option<PathBuf>,
/// `virtual_name` is the stable path rustc will store internally within
/// build artifacts.
virtual_name: PathBuf,
},
pub struct RealFileName {
/// The local name (always present in the original crate)
local: Option<InnerRealFileName>,
/// The maybe remapped part. Correspond to `local` when no remapped happened.
maybe_remapped: InnerRealFileName,
/// The remapped scopes. Any active scope MUST use `maybe_virtual`
scopes: RemapPathScopeComponents,
}
/// The inner workings of `RealFileName`.
///
/// It contains the `name`, `working_directory` and `embeddable_name` components.
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Decodable, Encodable, Hash)]
struct InnerRealFileName {
/// The name.
name: PathBuf,
/// The working directory associated with the embeddable name.
working_directory: PathBuf,
/// The embeddable name.
embeddable_name: PathBuf,
}
impl Hash for RealFileName {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
// To prevent #70924 from happening again we should only hash the
// remapped (virtualized) path if that exists. This is because
// virtualized paths to sysroot crates (/rust/$hash or /rust/$version)
// remain stable even if the corresponding local_path changes
self.remapped_path_if_available().hash(state)
// remapped path if that exists. This is because remapped paths to
// sysroot crates (/rust/$hash or /rust/$version) remain stable even
// if the corresponding local path changes.
if !self.scopes.is_all() {
self.local.hash(state);
}
self.maybe_remapped.hash(state);
self.scopes.bits().hash(state);
}
}
impl RealFileName {
/// Returns the path suitable for reading from the file system on the local host,
/// if this information exists.
/// Avoid embedding this in build artifacts; see `remapped_path_if_available()` for that.
pub fn local_path(&self) -> Option<&Path> {
match self {
RealFileName::LocalPath(p) => Some(p),
RealFileName::Remapped { local_path, virtual_name: _ } => local_path.as_deref(),
}
}
/// Returns the path suitable for reading from the file system on the local host,
/// if this information exists.
/// Avoid embedding this in build artifacts; see `remapped_path_if_available()` for that.
pub fn into_local_path(self) -> Option<PathBuf> {
match self {
RealFileName::LocalPath(p) => Some(p),
RealFileName::Remapped { local_path: p, virtual_name: _ } => p,
}
}
/// Returns the path suitable for embedding into build artifacts. This would still
/// be a local path if it has not been remapped. A remapped path will not correspond
/// to a valid file system path: see `local_path_if_available()` for something that
/// is more likely to return paths into the local host file system.
pub fn remapped_path_if_available(&self) -> &Path {
match self {
RealFileName::LocalPath(p)
| RealFileName::Remapped { local_path: _, virtual_name: p } => p,
}
}
/// Returns the path suitable for reading from the file system on the local host,
/// if this information exists. Otherwise returns the remapped name.
/// Avoid embedding this in build artifacts; see `remapped_path_if_available()` for that.
pub fn local_path_if_available(&self) -> &Path {
match self {
RealFileName::LocalPath(path)
| RealFileName::Remapped { local_path: None, virtual_name: path }
| RealFileName::Remapped { local_path: Some(path), virtual_name: _ } => path,
}
}
/// Return the path remapped or not depending on the [`FileNameDisplayPreference`].
/// Returns the associated path for the given remapping scope.
///
/// For the purpose of this function, local and short preference are equal.
pub fn to_path(&self, display_pref: FileNameDisplayPreference) -> &Path {
match display_pref {
FileNameDisplayPreference::Local | FileNameDisplayPreference::Short => {
self.local_path_if_available()
}
FileNameDisplayPreference::Remapped => self.remapped_path_if_available(),
/// ## Panic
///
/// Only one scope components can be given to this function.
pub fn path(&self, scope: RemapPathScopeComponents) -> &Path {
assert!(
scope.bits().count_ones() == 1,
"one and only one scope should be passed to `RealFileName::path`: {scope:?}"
);
if !self.scopes.contains(scope)
&& let Some(local_name) = &self.local
{
local_name.name.as_path()
} else {
self.maybe_remapped.name.as_path()
}
}
pub fn to_string_lossy(&self, display_pref: FileNameDisplayPreference) -> Cow<'_, str> {
/// Returns the working directory and embeddable path for the given remapping scope.
///
/// Useful for embedding a mostly abosolute path (modulo remapping) in the compiler outputs.
///
/// The embedabble path is not guaranteed to be an absolute path, nor is it garuenteed
/// that the working directory part is always a prefix of embeddable path.
///
/// ## Panic
///
/// Only one scope components can be given to this function.
pub fn embeddable_name(&self, scope: RemapPathScopeComponents) -> (&Path, &Path) {
assert!(
scope.bits().count_ones() == 1,
"one and only one scope should be passed to `RealFileName::embeddable_path`: {scope:?}"
);
if !self.scopes.contains(scope)
&& let Some(local_name) = &self.local
{
(&local_name.working_directory, &local_name.embeddable_name)
} else {
(&self.maybe_remapped.working_directory, &self.maybe_remapped.embeddable_name)
}
}
/// Returns the path suitable for reading from the file system on the local host,
/// if this information exists.
///
/// May not exists if the filename was imported from another crate.
pub fn local_path(&self) -> Option<&Path> {
self.local.as_ref().map(|lp| lp.name.as_ref())
}
/// Returns the path suitable for reading from the file system on the local host,
/// if this information exists.
///
/// May not exists if the filename was imported from another crate.
pub fn into_local_path(self) -> Option<PathBuf> {
self.local.map(|lp| lp.name)
}
/// Returns whenever the filename was remapped.
pub(crate) fn was_remapped(&self) -> bool {
!self.scopes.is_empty()
}
/// Returns an empty `RealFileName`
///
/// Useful as the working directory input to `SourceMap::to_real_filename`.
pub fn empty() -> RealFileName {
RealFileName {
local: Some(InnerRealFileName {
name: PathBuf::new(),
working_directory: PathBuf::new(),
embeddable_name: PathBuf::new(),
}),
maybe_remapped: InnerRealFileName {
name: PathBuf::new(),
working_directory: PathBuf::new(),
embeddable_name: PathBuf::new(),
},
scopes: RemapPathScopeComponents::empty(),
}
}
/// Returns a `RealFileName` that is completely remapped without any local components.
///
/// Only exposed for the purpose of `-Zsimulate-remapped-rust-src-base`.
pub fn from_virtual_path(path: &Path) -> RealFileName {
let name = InnerRealFileName {
name: path.to_owned(),
embeddable_name: path.to_owned(),
working_directory: PathBuf::new(),
};
RealFileName { local: None, maybe_remapped: name, scopes: RemapPathScopeComponents::all() }
}
/// Update the filename for encoding in the crate metadata.
///
/// Currently it's about removing the local part when the filename
/// is fully remapped.
pub fn update_for_crate_metadata(&mut self) {
if self.scopes.is_all() {
self.local = None;
}
}
/// Internal routine to display the filename.
///
/// Users should always use the `RealFileName::path` method or `FileName` methods instead.
fn to_string_lossy<'a>(&'a self, display_pref: FileNameDisplayPreference) -> Cow<'a, str> {
match display_pref {
FileNameDisplayPreference::Local => self.local_path_if_available().to_string_lossy(),
FileNameDisplayPreference::Remapped => {
self.remapped_path_if_available().to_string_lossy()
FileNameDisplayPreference::Remapped => self.maybe_remapped.name.to_string_lossy(),
FileNameDisplayPreference::Local => {
self.local.as_ref().unwrap_or(&self.maybe_remapped).name.to_string_lossy()
}
FileNameDisplayPreference::Short => self
.local_path_if_available()
.maybe_remapped
.name
.file_name()
.map_or_else(|| "".into(), |f| f.to_string_lossy()),
FileNameDisplayPreference::Scope(scope) => self.path(scope).to_string_lossy(),
}
}
}
@ -339,40 +467,20 @@ pub enum FileName {
InlineAsm(Hash64),
}
impl From<PathBuf> for FileName {
fn from(p: PathBuf) -> Self {
FileName::Real(RealFileName::LocalPath(p))
}
}
#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub enum FileNameEmbeddablePreference {
/// If a remapped path is available, only embed the `virtual_path` and omit the `local_path`.
///
/// Otherwise embed the local-path into the `virtual_path`.
RemappedOnly,
/// Embed the original path as well as its remapped `virtual_path` component if available.
LocalAndRemapped,
}
#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub enum FileNameDisplayPreference {
/// Display the path after the application of rewrite rules provided via `--remap-path-prefix`.
/// This is appropriate for paths that get embedded into files produced by the compiler.
Remapped,
/// Display the path before the application of rewrite rules provided via `--remap-path-prefix`.
/// This is appropriate for use in user-facing output (such as diagnostics).
Local,
/// Display only the filename, as a way to reduce the verbosity of the output.
/// This is appropriate for use in user-facing output (such as diagnostics).
Short,
}
pub struct FileNameDisplay<'a> {
inner: &'a FileName,
display_pref: FileNameDisplayPreference,
}
// Internal enum. Should not be exposed.
#[derive(Clone, Copy)]
enum FileNameDisplayPreference {
Remapped,
Local,
Short,
Scope(RemapPathScopeComponents),
}
impl fmt::Display for FileNameDisplay<'_> {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use FileName::*;
@ -417,18 +525,30 @@ impl FileName {
}
}
/// Returns the path suitable for reading from the file system on the local host,
/// if this information exists.
///
/// Avoid embedding this in build artifacts. Prefer using the `display` method.
pub fn prefer_remapped_unconditionally(&self) -> FileNameDisplay<'_> {
FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Remapped }
}
/// This may include transient local filesystem information.
/// Must not be embedded in build outputs.
pub fn prefer_local(&self) -> FileNameDisplay<'_> {
/// Returns the path suitable for reading from the file system on the local host,
/// if this information exists.
///
/// Avoid embedding this in build artifacts. Prefer using the `display` method.
pub fn prefer_local_unconditionally(&self) -> FileNameDisplay<'_> {
FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Local }
}
pub fn display(&self, display_pref: FileNameDisplayPreference) -> FileNameDisplay<'_> {
FileNameDisplay { inner: self, display_pref }
/// Returns a short (either the filename or an empty string).
pub fn short(&self) -> FileNameDisplay<'_> {
FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Short }
}
/// Returns a `Display`-able path for the given scope.
pub fn display(&self, scope: RemapPathScopeComponents) -> FileNameDisplay<'_> {
FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Scope(scope) }
}
pub fn macro_expansion_source_code(src: &str) -> FileName {
@ -473,7 +593,8 @@ impl FileName {
/// Returns the path suitable for reading from the file system on the local host,
/// if this information exists.
/// Avoid embedding this in build artifacts; see `remapped_path_if_available()` for that.
///
/// Avoid embedding this in build artifacts.
pub fn into_local_path(self) -> Option<PathBuf> {
match self {
FileName::Real(path) => path.into_local_path(),

View file

@ -2,6 +2,7 @@ use std::borrow::Borrow;
use rustc_data_structures::profiling::EventArgRecorder;
use crate::RemapPathScopeComponents;
use crate::source_map::SourceMap;
/// Extension trait for self-profiling purposes: allows to record spans within a generic activity's
@ -24,6 +25,6 @@ impl SpannedEventArgRecorder for EventArgRecorder<'_> {
A: Borrow<str> + Into<String>,
{
self.record_arg(event_arg);
self.record_arg(source_map.span_to_embeddable_string(span));
self.record_arg(source_map.span_to_string(span, RemapPathScopeComponents::DEBUGINFO));
}
}

Some files were not shown because too many files have changed in this diff Show more