Merge ref '2cd4ee6bcf' from rust-lang/rust
Pull recent changes from https://github.com/rust-lang/rust via Josh. Upstream ref:2cd4ee6bcfFiltered ref: 0fa640c05f720805b85aaf146087ed923ab5b9cb Upstream diff:dc47a69ed9...2cd4ee6bcfThis merge was created using https://github.com/rust-lang/josh-sync.
This commit is contained in:
commit
705ec58e00
179 changed files with 2249 additions and 1796 deletions
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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] } => {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
// tidy-alphabetical-start
|
||||
#![allow(internal_features)]
|
||||
#![deny(clippy::manual_let_else)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(file_buffered)]
|
||||
|
|
|
|||
|
|
@ -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)));
|
||||
|
|
|
|||
|
|
@ -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:?}")),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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()),
|
||||
)))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 } => {
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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`):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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\
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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 });
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// tidy-alphabetical-start
|
||||
#![deny(clippy::manual_let_else)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(if_let_guard)]
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
_ => {
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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, .. }) => {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)?;
|
||||
|
|
|
|||
|
|
@ -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) };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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}")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
"⚠",
|
||||
|
|
|
|||
|
|
@ -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" }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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],
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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" }
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue