Auto merge of #145366 - GuillaumeGomez:rollup-v0a6v3u, r=GuillaumeGomez
Rollup of 9 pull requests Successful merges: - rust-lang/rust#144761 (aarch64: Make `outline-atomics` a known target feature) - rust-lang/rust#144949 (More `Printer` cleanups) - rust-lang/rust#144955 (search graph: lazily update parent goals) - rust-lang/rust#144962 (Add aarch64_be-unknown-none-softfloat target) - rust-lang/rust#145153 (Handle macros with multiple kinds, and improve errors) - rust-lang/rust#145241 ([AVR] Changed data_layout) - rust-lang/rust#145341 (Install libgccjit into the compiler's sysroot when cg_gcc is enabled) - rust-lang/rust#145349 (Correctly handle when there are no unstable items in the documented crate) - rust-lang/rust#145356 (Add another example for escaped `#` character in doctest in rustdoc book) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
3672a55b7c
61 changed files with 946 additions and 508 deletions
|
|
@ -3889,6 +3889,7 @@ dependencies = [
|
|||
name = "rustc_hir"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"odht",
|
||||
"rustc_abi",
|
||||
"rustc_arena",
|
||||
|
|
|
|||
|
|
@ -436,14 +436,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
let body = Box::new(self.lower_delim_args(body));
|
||||
let def_id = self.local_def_id(id);
|
||||
let def_kind = self.tcx.def_kind(def_id);
|
||||
let DefKind::Macro(macro_kind) = def_kind else {
|
||||
let DefKind::Macro(macro_kinds) = def_kind else {
|
||||
unreachable!(
|
||||
"expected DefKind::Macro for macro item, found {}",
|
||||
def_kind.descr(def_id.to_def_id())
|
||||
);
|
||||
};
|
||||
let macro_def = self.arena.alloc(ast::MacroDef { body, macro_rules: *macro_rules });
|
||||
hir::ItemKind::Macro(ident, macro_def, macro_kind)
|
||||
hir::ItemKind::Macro(ident, macro_def, macro_kinds)
|
||||
}
|
||||
ItemKind::Delegation(box delegation) => {
|
||||
let delegation_results = self.lower_delegation(delegation, id, false);
|
||||
|
|
|
|||
|
|
@ -213,6 +213,12 @@ pub(crate) unsafe fn create_module<'ll>(
|
|||
target_data_layout = target_data_layout.replace("p8:128:128:128:48", "p8:128:128")
|
||||
}
|
||||
}
|
||||
if llvm_version < (22, 0, 0) {
|
||||
if sess.target.arch == "avr" {
|
||||
// LLVM 22.0 updated the default layout on avr: https://github.com/llvm/llvm-project/pull/153010
|
||||
target_data_layout = target_data_layout.replace("n8:16", "n8")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the data-layout values hardcoded remain the defaults.
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ use rustc_middle::bug;
|
|||
use rustc_middle::ty::print::{PrettyPrinter, PrintError, Printer};
|
||||
use rustc_middle::ty::{self, GenericArg, GenericArgKind, Ty, TyCtxt};
|
||||
|
||||
struct AbsolutePathPrinter<'tcx> {
|
||||
struct TypeNamePrinter<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
path: String,
|
||||
}
|
||||
|
||||
impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
|
||||
impl<'tcx> Printer<'tcx> for TypeNamePrinter<'tcx> {
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
|
@ -75,26 +75,26 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
|
|||
self.pretty_print_dyn_existential(predicates)
|
||||
}
|
||||
|
||||
fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
|
||||
fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
|
||||
self.path.push_str(self.tcx.crate_name(cnum).as_str());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn path_qualified(
|
||||
fn print_path_with_qualified(
|
||||
&mut self,
|
||||
self_ty: Ty<'tcx>,
|
||||
trait_ref: Option<ty::TraitRef<'tcx>>,
|
||||
) -> Result<(), PrintError> {
|
||||
self.pretty_path_qualified(self_ty, trait_ref)
|
||||
self.pretty_print_path_with_qualified(self_ty, trait_ref)
|
||||
}
|
||||
|
||||
fn path_append_impl(
|
||||
fn print_path_with_impl(
|
||||
&mut self,
|
||||
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
|
||||
self_ty: Ty<'tcx>,
|
||||
trait_ref: Option<ty::TraitRef<'tcx>>,
|
||||
) -> Result<(), PrintError> {
|
||||
self.pretty_path_append_impl(
|
||||
self.pretty_print_path_with_impl(
|
||||
|cx| {
|
||||
print_prefix(cx)?;
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
|
|||
)
|
||||
}
|
||||
|
||||
fn path_append(
|
||||
fn print_path_with_simple(
|
||||
&mut self,
|
||||
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
|
||||
disambiguated_data: &DisambiguatedDefPathData,
|
||||
|
|
@ -119,7 +119,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn path_generic_args(
|
||||
fn print_path_with_generic_args(
|
||||
&mut self,
|
||||
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
|
||||
args: &[GenericArg<'tcx>],
|
||||
|
|
@ -135,7 +135,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> {
|
||||
impl<'tcx> PrettyPrinter<'tcx> for TypeNamePrinter<'tcx> {
|
||||
fn should_print_region(&self, _region: ty::Region<'_>) -> bool {
|
||||
false
|
||||
}
|
||||
|
|
@ -159,7 +159,7 @@ impl<'tcx> PrettyPrinter<'tcx> for AbsolutePathPrinter<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl Write for AbsolutePathPrinter<'_> {
|
||||
impl Write for TypeNamePrinter<'_> {
|
||||
fn write_str(&mut self, s: &str) -> std::fmt::Result {
|
||||
self.path.push_str(s);
|
||||
Ok(())
|
||||
|
|
@ -167,7 +167,7 @@ impl Write for AbsolutePathPrinter<'_> {
|
|||
}
|
||||
|
||||
pub fn type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> String {
|
||||
let mut p = AbsolutePathPrinter { tcx, path: String::new() };
|
||||
let mut p = TypeNamePrinter { tcx, path: String::new() };
|
||||
p.print_type(ty).unwrap();
|
||||
p.path
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, PResult};
|
|||
use rustc_feature::Features;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::attrs::{AttributeKind, CfgEntry, Deprecation};
|
||||
use rustc_hir::def::MacroKinds;
|
||||
use rustc_hir::{Stability, find_attr};
|
||||
use rustc_lint_defs::{BufferedEarlyLint, RegisteredTools};
|
||||
use rustc_parse::MACRO_ARGUMENTS;
|
||||
|
|
@ -718,6 +719,9 @@ impl MacResult for DummyResult {
|
|||
/// A syntax extension kind.
|
||||
#[derive(Clone)]
|
||||
pub enum SyntaxExtensionKind {
|
||||
/// A `macro_rules!` macro that can work as any `MacroKind`
|
||||
MacroRules(Arc<crate::MacroRulesMacroExpander>),
|
||||
|
||||
/// A token-based function-like macro.
|
||||
Bang(
|
||||
/// An expander with signature TokenStream -> TokenStream.
|
||||
|
|
@ -772,9 +776,39 @@ pub enum SyntaxExtensionKind {
|
|||
),
|
||||
|
||||
/// A glob delegation.
|
||||
///
|
||||
/// This is for delegated function implementations, and has nothing to do with glob imports.
|
||||
GlobDelegation(Arc<dyn GlobDelegationExpander + sync::DynSync + sync::DynSend>),
|
||||
}
|
||||
|
||||
impl SyntaxExtensionKind {
|
||||
/// Returns `Some(expander)` for a macro usable as a `LegacyBang`; otherwise returns `None`
|
||||
///
|
||||
/// This includes a `MacroRules` with function-like rules.
|
||||
pub fn as_legacy_bang(&self) -> Option<&(dyn TTMacroExpander + sync::DynSync + sync::DynSend)> {
|
||||
match self {
|
||||
SyntaxExtensionKind::LegacyBang(exp) => Some(exp.as_ref()),
|
||||
SyntaxExtensionKind::MacroRules(exp) if exp.kinds().contains(MacroKinds::BANG) => {
|
||||
Some(exp.as_ref())
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `Some(expander)` for a macro usable as an `Attr`; otherwise returns `None`
|
||||
///
|
||||
/// This includes a `MacroRules` with `attr` rules.
|
||||
pub fn as_attr(&self) -> Option<&(dyn AttrProcMacro + sync::DynSync + sync::DynSend)> {
|
||||
match self {
|
||||
SyntaxExtensionKind::Attr(exp) => Some(exp.as_ref()),
|
||||
SyntaxExtensionKind::MacroRules(exp) if exp.kinds().contains(MacroKinds::ATTR) => {
|
||||
Some(exp.as_ref())
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A struct representing a macro definition in "lowered" form ready for expansion.
|
||||
pub struct SyntaxExtension {
|
||||
/// A syntax extension kind.
|
||||
|
|
@ -804,18 +838,19 @@ pub struct SyntaxExtension {
|
|||
}
|
||||
|
||||
impl SyntaxExtension {
|
||||
/// Returns which kind of macro calls this syntax extension.
|
||||
pub fn macro_kind(&self) -> MacroKind {
|
||||
/// Returns which kinds of macro call this syntax extension.
|
||||
pub fn macro_kinds(&self) -> MacroKinds {
|
||||
match self.kind {
|
||||
SyntaxExtensionKind::Bang(..)
|
||||
| SyntaxExtensionKind::LegacyBang(..)
|
||||
| SyntaxExtensionKind::GlobDelegation(..) => MacroKind::Bang,
|
||||
| SyntaxExtensionKind::GlobDelegation(..) => MacroKinds::BANG,
|
||||
SyntaxExtensionKind::Attr(..)
|
||||
| SyntaxExtensionKind::LegacyAttr(..)
|
||||
| SyntaxExtensionKind::NonMacroAttr => MacroKind::Attr,
|
||||
| SyntaxExtensionKind::NonMacroAttr => MacroKinds::ATTR,
|
||||
SyntaxExtensionKind::Derive(..) | SyntaxExtensionKind::LegacyDerive(..) => {
|
||||
MacroKind::Derive
|
||||
MacroKinds::DERIVE
|
||||
}
|
||||
SyntaxExtensionKind::MacroRules(ref m) => m.kinds(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1024,11 +1059,12 @@ impl SyntaxExtension {
|
|||
parent: LocalExpnId,
|
||||
call_site: Span,
|
||||
descr: Symbol,
|
||||
kind: MacroKind,
|
||||
macro_def_id: Option<DefId>,
|
||||
parent_module: Option<DefId>,
|
||||
) -> ExpnData {
|
||||
ExpnData::new(
|
||||
ExpnKind::Macro(self.macro_kind(), descr),
|
||||
ExpnKind::Macro(kind, descr),
|
||||
parent.to_expn_id(),
|
||||
call_site,
|
||||
self.span,
|
||||
|
|
|
|||
|
|
@ -736,8 +736,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
|
||||
let (fragment_kind, span) = (invoc.fragment_kind, invoc.span());
|
||||
ExpandResult::Ready(match invoc.kind {
|
||||
InvocationKind::Bang { mac, span } => match ext {
|
||||
SyntaxExtensionKind::Bang(expander) => {
|
||||
InvocationKind::Bang { mac, span } => {
|
||||
if let SyntaxExtensionKind::Bang(expander) = ext {
|
||||
match expander.expand(self.cx, span, mac.args.tokens.clone()) {
|
||||
Ok(tok_result) => {
|
||||
let fragment =
|
||||
|
|
@ -755,8 +755,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
}
|
||||
Err(guar) => return ExpandResult::Ready(fragment_kind.dummy(span, guar)),
|
||||
}
|
||||
}
|
||||
SyntaxExtensionKind::LegacyBang(expander) => {
|
||||
} else if let Some(expander) = ext.as_legacy_bang() {
|
||||
let tok_result = match expander.expand(self.cx, span, mac.args.tokens.clone()) {
|
||||
ExpandResult::Ready(tok_result) => tok_result,
|
||||
ExpandResult::Retry(_) => {
|
||||
|
|
@ -776,11 +775,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
let guar = self.error_wrong_fragment_kind(fragment_kind, &mac, span);
|
||||
fragment_kind.dummy(span, guar)
|
||||
}
|
||||
} else {
|
||||
unreachable!();
|
||||
}
|
||||
_ => unreachable!(),
|
||||
},
|
||||
InvocationKind::Attr { attr, pos, mut item, derives } => match ext {
|
||||
SyntaxExtensionKind::Attr(expander) => {
|
||||
}
|
||||
InvocationKind::Attr { attr, pos, mut item, derives } => {
|
||||
if let Some(expander) = ext.as_attr() {
|
||||
self.gate_proc_macro_input(&item);
|
||||
self.gate_proc_macro_attr_item(span, &item);
|
||||
let tokens = match &item {
|
||||
|
|
@ -835,8 +835,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
}
|
||||
Err(guar) => return ExpandResult::Ready(fragment_kind.dummy(span, guar)),
|
||||
}
|
||||
}
|
||||
SyntaxExtensionKind::LegacyAttr(expander) => {
|
||||
} else if let SyntaxExtensionKind::LegacyAttr(expander) = ext {
|
||||
match validate_attr::parse_meta(&self.cx.sess.psess, &attr) {
|
||||
Ok(meta) => {
|
||||
let item_clone = macro_stats.then(|| item.clone());
|
||||
|
|
@ -878,15 +877,15 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
fragment_kind.expect_from_annotatables(iter::once(item))
|
||||
}
|
||||
}
|
||||
}
|
||||
SyntaxExtensionKind::NonMacroAttr => {
|
||||
} else if let SyntaxExtensionKind::NonMacroAttr = ext {
|
||||
// `-Zmacro-stats` ignores these because they don't do any real expansion.
|
||||
self.cx.expanded_inert_attrs.mark(&attr);
|
||||
item.visit_attrs(|attrs| attrs.insert(pos, attr));
|
||||
fragment_kind.expect_from_annotatables(iter::once(item))
|
||||
} else {
|
||||
unreachable!();
|
||||
}
|
||||
_ => unreachable!(),
|
||||
},
|
||||
}
|
||||
InvocationKind::Derive { path, item, is_const } => match ext {
|
||||
SyntaxExtensionKind::Derive(expander)
|
||||
| SyntaxExtensionKind::LegacyDerive(expander) => {
|
||||
|
|
|
|||
|
|
@ -58,18 +58,6 @@ pub(super) fn failed_to_match_macro(
|
|||
|
||||
let Some(BestFailure { token, msg: label, remaining_matcher, .. }) = tracker.best_failure
|
||||
else {
|
||||
// FIXME: we should report this at macro resolution time, as we do for
|
||||
// `resolve_macro_cannot_use_as_attr`. We can do that once we track multiple macro kinds for a
|
||||
// Def.
|
||||
if attr_args.is_none() && !rules.iter().any(|rule| matches!(rule, MacroRule::Func { .. })) {
|
||||
let msg = format!("macro has no rules for function-like invocation `{name}!`");
|
||||
let mut err = psess.dcx().struct_span_err(sp, msg);
|
||||
if !def_head_span.is_dummy() {
|
||||
let msg = "this macro has no rules for function-like invocation";
|
||||
err.span_label(def_head_span, msg);
|
||||
}
|
||||
return (sp, err.emit());
|
||||
}
|
||||
return (sp, psess.dcx().span_delayed_bug(sp, "failed to match a macro"));
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -357,10 +357,10 @@ enum NestedMacroState {
|
|||
/// The token `macro_rules` was processed.
|
||||
MacroRules,
|
||||
/// The tokens `macro_rules!` were processed.
|
||||
MacroRulesNot,
|
||||
MacroRulesBang,
|
||||
/// The tokens `macro_rules!` followed by a name were processed. The name may be either directly
|
||||
/// an identifier or a meta-variable (that hopefully would be instantiated by an identifier).
|
||||
MacroRulesNotName,
|
||||
MacroRulesBangName,
|
||||
/// The keyword `macro` was processed.
|
||||
Macro,
|
||||
/// The keyword `macro` followed by a name was processed.
|
||||
|
|
@ -408,24 +408,24 @@ fn check_nested_occurrences(
|
|||
NestedMacroState::MacroRules,
|
||||
&TokenTree::Token(Token { kind: TokenKind::Bang, .. }),
|
||||
) => {
|
||||
state = NestedMacroState::MacroRulesNot;
|
||||
state = NestedMacroState::MacroRulesBang;
|
||||
}
|
||||
(
|
||||
NestedMacroState::MacroRulesNot,
|
||||
NestedMacroState::MacroRulesBang,
|
||||
&TokenTree::Token(Token { kind: TokenKind::Ident(..), .. }),
|
||||
) => {
|
||||
state = NestedMacroState::MacroRulesNotName;
|
||||
state = NestedMacroState::MacroRulesBangName;
|
||||
}
|
||||
(NestedMacroState::MacroRulesNot, &TokenTree::MetaVar(..)) => {
|
||||
state = NestedMacroState::MacroRulesNotName;
|
||||
(NestedMacroState::MacroRulesBang, &TokenTree::MetaVar(..)) => {
|
||||
state = NestedMacroState::MacroRulesBangName;
|
||||
// We check that the meta-variable is correctly used.
|
||||
check_occurrences(psess, node_id, tt, macros, binders, ops, guar);
|
||||
}
|
||||
(NestedMacroState::MacroRulesNotName, TokenTree::Delimited(.., del))
|
||||
(NestedMacroState::MacroRulesBangName, TokenTree::Delimited(.., del))
|
||||
| (NestedMacroState::MacroName, TokenTree::Delimited(.., del))
|
||||
if del.delim == Delimiter::Brace =>
|
||||
{
|
||||
let macro_rules = state == NestedMacroState::MacroRulesNotName;
|
||||
let macro_rules = state == NestedMacroState::MacroRulesBangName;
|
||||
state = NestedMacroState::Empty;
|
||||
let rest =
|
||||
check_nested_macro(psess, node_id, macro_rules, &del.tts, &nested_macros, guar);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan};
|
|||
use rustc_feature::Features;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::def::MacroKinds;
|
||||
use rustc_hir::find_attr;
|
||||
use rustc_lint_defs::BuiltinLintDiag;
|
||||
use rustc_lint_defs::builtin::{
|
||||
|
|
@ -144,6 +145,7 @@ pub struct MacroRulesMacroExpander {
|
|||
name: Ident,
|
||||
span: Span,
|
||||
transparency: Transparency,
|
||||
kinds: MacroKinds,
|
||||
rules: Vec<MacroRule>,
|
||||
}
|
||||
|
||||
|
|
@ -158,6 +160,10 @@ impl MacroRulesMacroExpander {
|
|||
};
|
||||
if has_compile_error_macro(rhs) { None } else { Some((&self.name, span)) }
|
||||
}
|
||||
|
||||
pub fn kinds(&self) -> MacroKinds {
|
||||
self.kinds
|
||||
}
|
||||
}
|
||||
|
||||
impl TTMacroExpander for MacroRulesMacroExpander {
|
||||
|
|
@ -540,13 +546,13 @@ pub fn compile_declarative_macro(
|
|||
span: Span,
|
||||
node_id: NodeId,
|
||||
edition: Edition,
|
||||
) -> (SyntaxExtension, Option<Arc<SyntaxExtension>>, usize) {
|
||||
) -> (SyntaxExtension, usize) {
|
||||
let mk_syn_ext = |kind| {
|
||||
let is_local = is_defined_in_current_crate(node_id);
|
||||
SyntaxExtension::new(sess, kind, span, Vec::new(), edition, ident.name, attrs, is_local)
|
||||
};
|
||||
let mk_bang_ext = |expander| mk_syn_ext(SyntaxExtensionKind::LegacyBang(expander));
|
||||
let dummy_syn_ext = |guar| (mk_bang_ext(Arc::new(DummyExpander(guar))), None, 0);
|
||||
let dummy_syn_ext =
|
||||
|guar| (mk_syn_ext(SyntaxExtensionKind::LegacyBang(Arc::new(DummyExpander(guar)))), 0);
|
||||
|
||||
let macro_rules = macro_def.macro_rules;
|
||||
let exp_sep = if macro_rules { exp!(Semi) } else { exp!(Comma) };
|
||||
|
|
@ -559,12 +565,12 @@ pub fn compile_declarative_macro(
|
|||
let mut guar = None;
|
||||
let mut check_emission = |ret: Result<(), ErrorGuaranteed>| guar = guar.or(ret.err());
|
||||
|
||||
let mut has_attr_rules = false;
|
||||
let mut kinds = MacroKinds::empty();
|
||||
let mut rules = Vec::new();
|
||||
|
||||
while p.token != token::Eof {
|
||||
let args = if p.eat_keyword_noexpect(sym::attr) {
|
||||
has_attr_rules = true;
|
||||
kinds |= MacroKinds::ATTR;
|
||||
if !features.macro_attr() {
|
||||
feature_err(sess, sym::macro_attr, span, "`macro_rules!` attributes are unstable")
|
||||
.emit();
|
||||
|
|
@ -581,6 +587,7 @@ pub fn compile_declarative_macro(
|
|||
}
|
||||
Some(args)
|
||||
} else {
|
||||
kinds |= MacroKinds::BANG;
|
||||
None
|
||||
};
|
||||
let lhs_tt = p.parse_token_tree();
|
||||
|
|
@ -627,6 +634,7 @@ pub fn compile_declarative_macro(
|
|||
let guar = sess.dcx().span_err(span, "macros must contain at least one rule");
|
||||
return dummy_syn_ext(guar);
|
||||
}
|
||||
assert!(!kinds.is_empty());
|
||||
|
||||
let transparency = find_attr!(attrs, AttributeKind::MacroTransparency(x) => *x)
|
||||
.unwrap_or(Transparency::fallback(macro_rules));
|
||||
|
|
@ -640,12 +648,8 @@ pub fn compile_declarative_macro(
|
|||
// Return the number of rules for unused rule linting, if this is a local macro.
|
||||
let nrules = if is_defined_in_current_crate(node_id) { rules.len() } else { 0 };
|
||||
|
||||
let exp = Arc::new(MacroRulesMacroExpander { name: ident, span, node_id, transparency, rules });
|
||||
let opt_attr_ext = has_attr_rules.then(|| {
|
||||
let exp = Arc::clone(&exp);
|
||||
Arc::new(mk_syn_ext(SyntaxExtensionKind::Attr(exp)))
|
||||
});
|
||||
(mk_bang_ext(exp), opt_attr_ext, nrules)
|
||||
let exp = MacroRulesMacroExpander { name: ident, kinds, span, node_id, transparency, rules };
|
||||
(mk_syn_ext(SyntaxExtensionKind::MacroRules(Arc::new(exp))), nrules)
|
||||
}
|
||||
|
||||
fn check_no_eof(sess: &Session, p: &Parser<'_>, msg: &'static str) -> Option<ErrorGuaranteed> {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ edition = "2024"
|
|||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
bitflags = "2.9.1"
|
||||
odht = { version = "0.3.1", features = ["nightly"] }
|
||||
rustc_abi = { path = "../rustc_abi" }
|
||||
rustc_arena = { path = "../rustc_arena" }
|
||||
|
|
|
|||
|
|
@ -31,6 +31,53 @@ pub enum CtorKind {
|
|||
Const,
|
||||
}
|
||||
|
||||
/// A set of macro kinds, for macros that can have more than one kind
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Hash, Debug)]
|
||||
#[derive(HashStable_Generic)]
|
||||
pub struct MacroKinds(u8);
|
||||
bitflags::bitflags! {
|
||||
impl MacroKinds: u8 {
|
||||
const BANG = 1 << 0;
|
||||
const ATTR = 1 << 1;
|
||||
const DERIVE = 1 << 2;
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MacroKind> for MacroKinds {
|
||||
fn from(kind: MacroKind) -> Self {
|
||||
match kind {
|
||||
MacroKind::Bang => Self::BANG,
|
||||
MacroKind::Attr => Self::ATTR,
|
||||
MacroKind::Derive => Self::DERIVE,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MacroKinds {
|
||||
/// Convert the MacroKinds to a static string.
|
||||
///
|
||||
/// This hardcodes all the possibilities, in order to return a static string.
|
||||
pub fn descr(self) -> &'static str {
|
||||
match self {
|
||||
// FIXME: change this to "function-like macro" and fix all tests
|
||||
Self::BANG => "macro",
|
||||
Self::ATTR => "attribute macro",
|
||||
Self::DERIVE => "derive macro",
|
||||
_ if self == (Self::ATTR | Self::BANG) => "attribute/function macro",
|
||||
_ if self == (Self::DERIVE | Self::BANG) => "derive/function macro",
|
||||
_ if self == (Self::ATTR | Self::DERIVE) => "attribute/derive macro",
|
||||
_ if self.is_all() => "attribute/derive/function macro",
|
||||
_ if self.is_empty() => "useless macro",
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return an indefinite article (a/an) for use with `descr()`
|
||||
pub fn article(self) -> &'static str {
|
||||
if self.contains(Self::ATTR) { "an" } else { "a" }
|
||||
}
|
||||
}
|
||||
|
||||
/// An attribute that is not a macro; e.g., `#[inline]` or `#[rustfmt::skip]`.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug, HashStable_Generic)]
|
||||
pub enum NonMacroAttrKind {
|
||||
|
|
@ -101,7 +148,7 @@ pub enum DefKind {
|
|||
AssocConst,
|
||||
|
||||
// Macro namespace
|
||||
Macro(MacroKind),
|
||||
Macro(MacroKinds),
|
||||
|
||||
// Not namespaced (or they are, but we don't treat them so)
|
||||
ExternCrate,
|
||||
|
|
@ -177,7 +224,7 @@ impl DefKind {
|
|||
DefKind::AssocConst => "associated constant",
|
||||
DefKind::TyParam => "type parameter",
|
||||
DefKind::ConstParam => "const parameter",
|
||||
DefKind::Macro(macro_kind) => macro_kind.descr(),
|
||||
DefKind::Macro(kinds) => kinds.descr(),
|
||||
DefKind::LifetimeParam => "lifetime parameter",
|
||||
DefKind::Use => "import",
|
||||
DefKind::ForeignMod => "foreign module",
|
||||
|
|
@ -208,7 +255,7 @@ impl DefKind {
|
|||
| DefKind::Use
|
||||
| DefKind::InlineConst
|
||||
| DefKind::ExternCrate => "an",
|
||||
DefKind::Macro(macro_kind) => macro_kind.article(),
|
||||
DefKind::Macro(kinds) => kinds.article(),
|
||||
_ => "a",
|
||||
}
|
||||
}
|
||||
|
|
@ -845,10 +892,10 @@ impl<Id> Res<Id> {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn macro_kind(self) -> Option<MacroKind> {
|
||||
pub fn macro_kinds(self) -> Option<MacroKinds> {
|
||||
match self {
|
||||
Res::Def(DefKind::Macro(kind), _) => Some(kind),
|
||||
Res::NonMacroAttr(..) => Some(MacroKind::Attr),
|
||||
Res::Def(DefKind::Macro(kinds), _) => Some(kinds),
|
||||
Res::NonMacroAttr(..) => Some(MacroKinds::ATTR),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ use rustc_data_structures::tagged_ptr::TaggedRef;
|
|||
use rustc_index::IndexVec;
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::{BytePos, DUMMY_SP, ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
|
||||
use rustc_target::asm::InlineAsmRegOrRegClass;
|
||||
|
|
@ -30,7 +29,7 @@ use tracing::debug;
|
|||
|
||||
use crate::LangItem;
|
||||
use crate::attrs::AttributeKind;
|
||||
use crate::def::{CtorKind, DefKind, PerNS, Res};
|
||||
use crate::def::{CtorKind, DefKind, MacroKinds, PerNS, Res};
|
||||
use crate::def_id::{DefId, LocalDefIdMap};
|
||||
pub(crate) use crate::hir_id::{HirId, ItemLocalId, ItemLocalMap, OwnerId};
|
||||
use crate::intravisit::{FnKind, VisitorExt};
|
||||
|
|
@ -4157,7 +4156,7 @@ impl<'hir> Item<'hir> {
|
|||
expect_fn, (Ident, &FnSig<'hir>, &'hir Generics<'hir>, BodyId),
|
||||
ItemKind::Fn { ident, sig, generics, body, .. }, (*ident, sig, generics, *body);
|
||||
|
||||
expect_macro, (Ident, &ast::MacroDef, MacroKind),
|
||||
expect_macro, (Ident, &ast::MacroDef, MacroKinds),
|
||||
ItemKind::Macro(ident, def, mk), (*ident, def, *mk);
|
||||
|
||||
expect_mod, (Ident, &'hir Mod<'hir>), ItemKind::Mod(ident, m), (*ident, m);
|
||||
|
|
@ -4336,7 +4335,7 @@ pub enum ItemKind<'hir> {
|
|||
has_body: bool,
|
||||
},
|
||||
/// A MBE macro definition (`macro_rules!` or `macro`).
|
||||
Macro(Ident, &'hir ast::MacroDef, MacroKind),
|
||||
Macro(Ident, &'hir ast::MacroDef, MacroKinds),
|
||||
/// A module.
|
||||
Mod(Ident, &'hir Mod<'hir>),
|
||||
/// An external module, e.g. `extern { .. }`.
|
||||
|
|
|
|||
|
|
@ -745,12 +745,12 @@ impl<'tcx> LateContext<'tcx> {
|
|||
/// }
|
||||
/// ```
|
||||
pub fn get_def_path(&self, def_id: DefId) -> Vec<Symbol> {
|
||||
struct AbsolutePathPrinter<'tcx> {
|
||||
struct LintPathPrinter<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
path: Vec<Symbol>,
|
||||
}
|
||||
|
||||
impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
|
||||
impl<'tcx> Printer<'tcx> for LintPathPrinter<'tcx> {
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
|
@ -774,12 +774,12 @@ impl<'tcx> LateContext<'tcx> {
|
|||
unreachable!(); // because `path_generic_args` ignores the `GenericArgs`
|
||||
}
|
||||
|
||||
fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
|
||||
fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
|
||||
self.path = vec![self.tcx.crate_name(cnum)];
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn path_qualified(
|
||||
fn print_path_with_qualified(
|
||||
&mut self,
|
||||
self_ty: Ty<'tcx>,
|
||||
trait_ref: Option<ty::TraitRef<'tcx>>,
|
||||
|
|
@ -800,7 +800,7 @@ impl<'tcx> LateContext<'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
fn path_append_impl(
|
||||
fn print_path_with_impl(
|
||||
&mut self,
|
||||
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
|
||||
self_ty: Ty<'tcx>,
|
||||
|
|
@ -825,7 +825,7 @@ impl<'tcx> LateContext<'tcx> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn path_append(
|
||||
fn print_path_with_simple(
|
||||
&mut self,
|
||||
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
|
||||
disambiguated_data: &DisambiguatedDefPathData,
|
||||
|
|
@ -844,7 +844,7 @@ impl<'tcx> LateContext<'tcx> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn path_generic_args(
|
||||
fn print_path_with_generic_args(
|
||||
&mut self,
|
||||
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
|
||||
_args: &[GenericArg<'tcx>],
|
||||
|
|
@ -853,7 +853,7 @@ impl<'tcx> LateContext<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
let mut p = AbsolutePathPrinter { tcx: self.tcx, path: vec![] };
|
||||
let mut p = LintPathPrinter { tcx: self.tcx, path: vec![] };
|
||||
p.print_def_path(def_id, &[]).unwrap();
|
||||
p.path
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use rustc_hir::{Body, HirId, Item, ItemKind, Node, Path, TyKind};
|
|||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::{declare_lint, impl_lint_pass};
|
||||
use rustc_span::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc_span::{ExpnKind, MacroKind, Span, kw, sym};
|
||||
use rustc_span::{ExpnKind, Span, kw, sym};
|
||||
|
||||
use crate::lints::{NonLocalDefinitionsCargoUpdateNote, NonLocalDefinitionsDiag};
|
||||
use crate::{LateContext, LateLintPass, LintContext, fluent_generated as fluent};
|
||||
|
|
@ -240,7 +240,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
|
|||
},
|
||||
)
|
||||
}
|
||||
ItemKind::Macro(_, _macro, MacroKind::Bang)
|
||||
ItemKind::Macro(_, _macro, _kinds)
|
||||
if cx.tcx.has_attr(item.owner_id.def_id, sym::macro_export) =>
|
||||
{
|
||||
cx.emit_span_lint(
|
||||
|
|
|
|||
|
|
@ -1981,7 +1981,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
def_key.disambiguated_data.data = DefPathData::MacroNs(name);
|
||||
|
||||
let def_id = id.to_def_id();
|
||||
self.tables.def_kind.set_some(def_id.index, DefKind::Macro(macro_kind));
|
||||
self.tables.def_kind.set_some(def_id.index, DefKind::Macro(macro_kind.into()));
|
||||
self.tables.proc_macro.set_some(def_id.index, macro_kind);
|
||||
self.encode_attrs(id);
|
||||
record!(self.tables.def_keys[def_id] <- def_key);
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use rustc_abi::{FieldIdx, ReprOptions, VariantIdx};
|
|||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::svh::Svh;
|
||||
use rustc_hir::attrs::StrippedCfgItem;
|
||||
use rustc_hir::def::{CtorKind, DefKind, DocLinkResMap};
|
||||
use rustc_hir::def::{CtorKind, DefKind, DocLinkResMap, MacroKinds};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIndex, DefPathHash, StableCrateId};
|
||||
use rustc_hir::definitions::DefKey;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ impl FixedSizeEncoding for u64 {
|
|||
}
|
||||
|
||||
macro_rules! fixed_size_enum {
|
||||
($ty:ty { $(($($pat:tt)*))* }) => {
|
||||
($ty:ty { $(($($pat:tt)*))* } $( unreachable { $(($($upat:tt)*))+ } )?) => {
|
||||
impl FixedSizeEncoding for Option<$ty> {
|
||||
type ByteArray = [u8;1];
|
||||
|
||||
|
|
@ -103,12 +103,24 @@ macro_rules! fixed_size_enum {
|
|||
b[0] = match self {
|
||||
None => unreachable!(),
|
||||
$(Some($($pat)*) => 1 + ${index()},)*
|
||||
$(Some($($($upat)*)|+) => unreachable!(),)?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround; need const traits to construct bitflags in a const
|
||||
macro_rules! const_macro_kinds {
|
||||
($($name:ident),+$(,)?) => (MacroKinds::from_bits_truncate($(MacroKinds::$name.bits())|+))
|
||||
}
|
||||
const MACRO_KINDS_ATTR_BANG: MacroKinds = const_macro_kinds!(ATTR, BANG);
|
||||
const MACRO_KINDS_DERIVE_BANG: MacroKinds = const_macro_kinds!(DERIVE, BANG);
|
||||
const MACRO_KINDS_DERIVE_ATTR: MacroKinds = const_macro_kinds!(DERIVE, ATTR);
|
||||
const MACRO_KINDS_DERIVE_ATTR_BANG: MacroKinds = const_macro_kinds!(DERIVE, ATTR, BANG);
|
||||
// Ensure that we get a compilation error if MacroKinds gets extended without updating metadata.
|
||||
const _: () = assert!(MACRO_KINDS_DERIVE_ATTR_BANG.is_all());
|
||||
|
||||
fixed_size_enum! {
|
||||
DefKind {
|
||||
( Mod )
|
||||
|
|
@ -151,10 +163,16 @@ fixed_size_enum! {
|
|||
( Ctor(CtorOf::Struct, CtorKind::Const) )
|
||||
( Ctor(CtorOf::Variant, CtorKind::Fn) )
|
||||
( Ctor(CtorOf::Variant, CtorKind::Const) )
|
||||
( Macro(MacroKind::Bang) )
|
||||
( Macro(MacroKind::Attr) )
|
||||
( Macro(MacroKind::Derive) )
|
||||
( Macro(MacroKinds::BANG) )
|
||||
( Macro(MacroKinds::ATTR) )
|
||||
( Macro(MacroKinds::DERIVE) )
|
||||
( Macro(MACRO_KINDS_ATTR_BANG) )
|
||||
( Macro(MACRO_KINDS_DERIVE_ATTR) )
|
||||
( Macro(MACRO_KINDS_DERIVE_BANG) )
|
||||
( Macro(MACRO_KINDS_DERIVE_ATTR_BANG) )
|
||||
( SyntheticCoroutineBody )
|
||||
} unreachable {
|
||||
( Macro(_) )
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1932,7 +1932,7 @@ fn pretty_print_const_value_tcx<'tcx>(
|
|||
let args = tcx.lift(args).unwrap();
|
||||
let mut p = FmtPrinter::new(tcx, Namespace::ValueNS);
|
||||
p.print_alloc_ids = true;
|
||||
p.print_value_path(variant_def.def_id, args)?;
|
||||
p.pretty_print_value_path(variant_def.def_id, args)?;
|
||||
fmt.write_str(&p.into_buffer())?;
|
||||
|
||||
match variant_def.ctor_kind() {
|
||||
|
|
@ -1974,7 +1974,7 @@ fn pretty_print_const_value_tcx<'tcx>(
|
|||
(ConstValue::ZeroSized, ty::FnDef(d, s)) => {
|
||||
let mut p = FmtPrinter::new(tcx, Namespace::ValueNS);
|
||||
p.print_alloc_ids = true;
|
||||
p.print_value_path(*d, s)?;
|
||||
p.pretty_print_value_path(*d, s)?;
|
||||
fmt.write_str(&p.into_buffer())?;
|
||||
return Ok(());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,18 +19,16 @@ pub trait Print<'tcx, P> {
|
|||
fn print(&self, p: &mut P) -> Result<(), PrintError>;
|
||||
}
|
||||
|
||||
/// Interface for outputting user-facing "type-system entities"
|
||||
/// (paths, types, lifetimes, constants, etc.) as a side-effect
|
||||
/// (e.g. formatting, like `PrettyPrinter` implementors do) or by
|
||||
/// constructing some alternative representation (e.g. an AST),
|
||||
/// which the associated types allow passing through the methods.
|
||||
///
|
||||
/// For pretty-printing/formatting in particular, see `PrettyPrinter`.
|
||||
//
|
||||
// FIXME(eddyb) find a better name; this is more general than "printing".
|
||||
/// A trait that "prints" user-facing type system entities: paths, types, lifetimes, constants,
|
||||
/// etc. "Printing" here means building up a representation of the entity's path, usually as a
|
||||
/// `String` (e.g. "std::io::Read") or a `Vec<Symbol>` (e.g. `[sym::std, sym::io, sym::Read]`). The
|
||||
/// representation is built up by appending one or more pieces. The specific details included in
|
||||
/// the built-up representation depend on the purpose of the printer. The more advanced printers
|
||||
/// also rely on the `PrettyPrinter` sub-trait.
|
||||
pub trait Printer<'tcx>: Sized {
|
||||
fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
|
||||
|
||||
/// Appends a representation of an entity with a normal path, e.g. "std::io::Read".
|
||||
fn print_def_path(
|
||||
&mut self,
|
||||
def_id: DefId,
|
||||
|
|
@ -39,6 +37,7 @@ pub trait Printer<'tcx>: Sized {
|
|||
self.default_print_def_path(def_id, args)
|
||||
}
|
||||
|
||||
/// Like `print_def_path`, but for `DefPathData::Impl`.
|
||||
fn print_impl_path(
|
||||
&mut self,
|
||||
impl_def_id: DefId,
|
||||
|
|
@ -64,47 +63,66 @@ pub trait Printer<'tcx>: Sized {
|
|||
self.default_print_impl_path(impl_def_id, self_ty, impl_trait_ref)
|
||||
}
|
||||
|
||||
/// Appends a representation of a region.
|
||||
fn print_region(&mut self, region: ty::Region<'tcx>) -> Result<(), PrintError>;
|
||||
|
||||
/// Appends a representation of a type.
|
||||
fn print_type(&mut self, ty: Ty<'tcx>) -> Result<(), PrintError>;
|
||||
|
||||
/// Appends a representation of a list of `PolyExistentialPredicate`s.
|
||||
fn print_dyn_existential(
|
||||
&mut self,
|
||||
predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
||||
) -> Result<(), PrintError>;
|
||||
|
||||
/// Appends a representation of a const.
|
||||
fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError>;
|
||||
|
||||
fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError>;
|
||||
/// Appends a representation of a crate name, e.g. `std`, or even ``.
|
||||
fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError>;
|
||||
|
||||
fn path_qualified(
|
||||
&mut self,
|
||||
self_ty: Ty<'tcx>,
|
||||
trait_ref: Option<ty::TraitRef<'tcx>>,
|
||||
) -> Result<(), PrintError>;
|
||||
|
||||
fn path_append_impl(
|
||||
&mut self,
|
||||
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
|
||||
self_ty: Ty<'tcx>,
|
||||
trait_ref: Option<ty::TraitRef<'tcx>>,
|
||||
) -> Result<(), PrintError>;
|
||||
|
||||
fn path_append(
|
||||
/// Appends a representation of a (full or partial) simple path, in two parts. `print_prefix`,
|
||||
/// when called, appends the representation of the leading segments. The rest of the method
|
||||
/// appends the representation of the final segment, the details of which are in
|
||||
/// `disambiguated_data`.
|
||||
///
|
||||
/// E.g. `std::io` + `Read` -> `std::io::Read`.
|
||||
fn print_path_with_simple(
|
||||
&mut self,
|
||||
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
|
||||
disambiguated_data: &DisambiguatedDefPathData,
|
||||
) -> Result<(), PrintError>;
|
||||
|
||||
fn path_generic_args(
|
||||
/// Similar to `print_path_with_simple`, but the final segment is an `impl` segment.
|
||||
///
|
||||
/// E.g. `slice` + `<impl [T]>` -> `slice::<impl [T]>`, which may then be further appended to,
|
||||
/// giving a longer path representation such as `slice::<impl [T]>::to_vec_in::ConvertVec`.
|
||||
fn print_path_with_impl(
|
||||
&mut self,
|
||||
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
|
||||
self_ty: Ty<'tcx>,
|
||||
trait_ref: Option<ty::TraitRef<'tcx>>,
|
||||
) -> Result<(), PrintError>;
|
||||
|
||||
/// Appends a representation of a path ending in generic args, in two parts. `print_prefix`,
|
||||
/// when called, appends the leading segments. The rest of the method appends the
|
||||
/// representation of the generic args. (Some printers choose to skip appending the generic
|
||||
/// args.)
|
||||
///
|
||||
/// E.g. `ImplementsTraitForUsize` + `<usize>` -> `ImplementsTraitForUsize<usize>`.
|
||||
fn print_path_with_generic_args(
|
||||
&mut self,
|
||||
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
|
||||
args: &[GenericArg<'tcx>],
|
||||
) -> Result<(), PrintError>;
|
||||
|
||||
fn should_truncate(&mut self) -> bool {
|
||||
false
|
||||
}
|
||||
/// Appends a representation of a qualified path segment, e.g. `<OsString as From<&T>>`.
|
||||
/// If `trait_ref` is `None`, it may fall back to simpler forms, e.g. `<Vec<T>>` or just `Foo`.
|
||||
fn print_path_with_qualified(
|
||||
&mut self,
|
||||
self_ty: Ty<'tcx>,
|
||||
trait_ref: Option<ty::TraitRef<'tcx>>,
|
||||
) -> Result<(), PrintError>;
|
||||
|
||||
// Defaults (should not be overridden):
|
||||
|
||||
|
|
@ -120,7 +138,7 @@ pub trait Printer<'tcx>: Sized {
|
|||
match key.disambiguated_data.data {
|
||||
DefPathData::CrateRoot => {
|
||||
assert!(key.parent.is_none());
|
||||
self.path_crate(def_id.krate)
|
||||
self.print_crate_name(def_id.krate)
|
||||
}
|
||||
|
||||
DefPathData::Impl => self.print_impl_path(def_id, args),
|
||||
|
|
@ -144,7 +162,7 @@ pub trait Printer<'tcx>: Sized {
|
|||
)) = self.tcx().coroutine_kind(def_id)
|
||||
&& args.len() > parent_args.len()
|
||||
{
|
||||
return self.path_generic_args(
|
||||
return self.print_path_with_generic_args(
|
||||
|p| p.print_def_path(def_id, parent_args),
|
||||
&args[..parent_args.len() + 1][..1],
|
||||
);
|
||||
|
|
@ -166,7 +184,7 @@ pub trait Printer<'tcx>: Sized {
|
|||
_ => {
|
||||
if !generics.is_own_empty() && args.len() >= generics.count() {
|
||||
let args = generics.own_args_no_defaults(self.tcx(), args);
|
||||
return self.path_generic_args(
|
||||
return self.print_path_with_generic_args(
|
||||
|p| p.print_def_path(def_id, parent_args),
|
||||
args,
|
||||
);
|
||||
|
|
@ -182,7 +200,7 @@ pub trait Printer<'tcx>: Sized {
|
|||
&& self.tcx().generics_of(parent_def_id).parent_count == 0;
|
||||
}
|
||||
|
||||
self.path_append(
|
||||
self.print_path_with_simple(
|
||||
|p: &mut Self| {
|
||||
if trait_qualify_parent {
|
||||
let trait_ref = ty::TraitRef::new(
|
||||
|
|
@ -190,7 +208,7 @@ pub trait Printer<'tcx>: Sized {
|
|||
parent_def_id,
|
||||
parent_args.iter().copied(),
|
||||
);
|
||||
p.path_qualified(trait_ref.self_ty(), Some(trait_ref))
|
||||
p.print_path_with_qualified(trait_ref.self_ty(), Some(trait_ref))
|
||||
} else {
|
||||
p.print_def_path(parent_def_id, parent_args)
|
||||
}
|
||||
|
|
@ -233,11 +251,15 @@ pub trait Printer<'tcx>: Sized {
|
|||
// If the impl is not co-located with either self-type or
|
||||
// trait-type, then fallback to a format that identifies
|
||||
// the module more clearly.
|
||||
self.path_append_impl(|p| p.print_def_path(parent_def_id, &[]), self_ty, impl_trait_ref)
|
||||
self.print_path_with_impl(
|
||||
|p| p.print_def_path(parent_def_id, &[]),
|
||||
self_ty,
|
||||
impl_trait_ref,
|
||||
)
|
||||
} else {
|
||||
// Otherwise, try to give a good form that would be valid language
|
||||
// syntax. Preferably using associated item notation.
|
||||
self.path_qualified(self_ty, impl_trait_ref)
|
||||
self.print_path_with_qualified(self_ty, impl_trait_ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ impl<'tcx> RegionHighlightMode<'tcx> {
|
|||
/// Trait for printers that pretty-print using `fmt::Write` to the printer.
|
||||
pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||
/// Like `print_def_path` but for value paths.
|
||||
fn print_value_path(
|
||||
fn pretty_print_value_path(
|
||||
&mut self,
|
||||
def_id: DefId,
|
||||
args: &'tcx [GenericArg<'tcx>],
|
||||
|
|
@ -253,7 +253,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
self.print_def_path(def_id, args)
|
||||
}
|
||||
|
||||
fn print_in_binder<T>(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), PrintError>
|
||||
fn pretty_print_in_binder<T>(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), PrintError>
|
||||
where
|
||||
T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
|
|
@ -333,6 +333,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
f: impl FnOnce(&mut Self) -> Result<(), PrintError>,
|
||||
) -> Result<(), PrintError>;
|
||||
|
||||
fn should_truncate(&mut self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
/// Returns `true` if the region should be printed in
|
||||
/// optional positions, e.g., `&'a T` or `dyn Tr + 'b`.
|
||||
/// This is typically the case for all non-`'_` regions.
|
||||
|
|
@ -470,7 +474,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
// path to the crate followed by the path to the item within the crate.
|
||||
if let Some(cnum) = def_id.as_crate_root() {
|
||||
if cnum == LOCAL_CRATE {
|
||||
self.path_crate(cnum)?;
|
||||
self.print_crate_name(cnum)?;
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
|
|
@ -494,7 +498,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
// or avoid ending up with `ExternCrateSource::Extern`,
|
||||
// for the injected `std`/`core`.
|
||||
if span.is_dummy() {
|
||||
self.path_crate(cnum)?;
|
||||
self.print_crate_name(cnum)?;
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
|
|
@ -508,13 +512,13 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
return Ok(true);
|
||||
}
|
||||
(ExternCrateSource::Path, LOCAL_CRATE) => {
|
||||
self.path_crate(cnum)?;
|
||||
self.print_crate_name(cnum)?;
|
||||
return Ok(true);
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
None => {
|
||||
self.path_crate(cnum)?;
|
||||
self.print_crate_name(cnum)?;
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -624,7 +628,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
return Ok(false);
|
||||
}
|
||||
callers.push(visible_parent);
|
||||
// HACK(eddyb) this bypasses `path_append`'s prefix printing to avoid
|
||||
// HACK(eddyb) this bypasses `print_path_with_simple`'s prefix printing to avoid
|
||||
// knowing ahead of time whether the entire path will succeed or not.
|
||||
// To support printers that do not implement `PrettyPrinter`, a `Vec` or
|
||||
// linked list on the stack would need to be built, before any printing.
|
||||
|
|
@ -633,11 +637,14 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
true => {}
|
||||
}
|
||||
callers.pop();
|
||||
self.path_append(|_| Ok(()), &DisambiguatedDefPathData { data, disambiguator: 0 })?;
|
||||
self.print_path_with_simple(
|
||||
|_| Ok(()),
|
||||
&DisambiguatedDefPathData { data, disambiguator: 0 },
|
||||
)?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn pretty_path_qualified(
|
||||
fn pretty_print_path_with_qualified(
|
||||
&mut self,
|
||||
self_ty: Ty<'tcx>,
|
||||
trait_ref: Option<ty::TraitRef<'tcx>>,
|
||||
|
|
@ -672,7 +679,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
})
|
||||
}
|
||||
|
||||
fn pretty_path_append_impl(
|
||||
fn pretty_print_path_with_impl(
|
||||
&mut self,
|
||||
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
|
||||
self_ty: Ty<'tcx>,
|
||||
|
|
@ -739,7 +746,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
}
|
||||
sig.print(self)?;
|
||||
write!(self, " {{")?;
|
||||
self.print_value_path(def_id, args)?;
|
||||
self.pretty_print_value_path(def_id, args)?;
|
||||
write!(self, "}}")?;
|
||||
}
|
||||
}
|
||||
|
|
@ -1308,10 +1315,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
alias_ty: ty::AliasTerm<'tcx>,
|
||||
) -> Result<(), PrintError> {
|
||||
let def_key = self.tcx().def_key(alias_ty.def_id);
|
||||
self.path_generic_args(
|
||||
self.print_path_with_generic_args(
|
||||
|p| {
|
||||
p.path_append(
|
||||
|p| p.path_qualified(alias_ty.self_ty(), None),
|
||||
p.print_path_with_simple(
|
||||
|p| p.print_path_with_qualified(alias_ty.self_ty(), None),
|
||||
&def_key.disambiguated_data,
|
||||
)
|
||||
},
|
||||
|
|
@ -1386,7 +1393,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
if let ty::Tuple(tys) = principal.args.type_at(0).kind() {
|
||||
let mut projections = predicates.projection_bounds();
|
||||
if let (Some(proj), None) = (projections.next(), projections.next()) {
|
||||
p.pretty_fn_sig(
|
||||
p.pretty_print_fn_sig(
|
||||
tys,
|
||||
false,
|
||||
proj.skip_binder().term.as_type().expect("Return type was a const"),
|
||||
|
|
@ -1396,7 +1403,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
}
|
||||
}
|
||||
|
||||
// HACK(eddyb) this duplicates `FmtPrinter`'s `path_generic_args`,
|
||||
// HACK(eddyb) this duplicates `FmtPrinter`'s `print_path_with_generic_args`,
|
||||
// in order to place the projections inside the `<...>`.
|
||||
if !resugared {
|
||||
let principal_with_self =
|
||||
|
|
@ -1488,7 +1495,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn pretty_fn_sig(
|
||||
fn pretty_print_fn_sig(
|
||||
&mut self,
|
||||
inputs: &[Ty<'tcx>],
|
||||
c_variadic: bool,
|
||||
|
|
@ -1525,7 +1532,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) => {
|
||||
match self.tcx().def_kind(def) {
|
||||
DefKind::Const | DefKind::AssocConst => {
|
||||
self.print_value_path(def, args)?;
|
||||
self.pretty_print_value_path(def, args)?;
|
||||
}
|
||||
DefKind::AnonConst => {
|
||||
if def.is_local()
|
||||
|
|
@ -1534,13 +1541,13 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
{
|
||||
write!(self, "{snip}")?;
|
||||
} else {
|
||||
// Do not call `print_value_path` as if a parent of this anon const is
|
||||
// an impl it will attempt to print out the impl trait ref i.e. `<T as
|
||||
// Trait>::{constant#0}`. This would cause printing to enter an
|
||||
// infinite recursion if the anon const is in the self type i.e.
|
||||
// `impl<T: Default> Default for [T; 32 - 1 - 1 - 1] {` where we would
|
||||
// try to print
|
||||
// `<[T; /* print constant#0 again */] as // Default>::{constant#0}`.
|
||||
// Do not call `pretty_print_value_path` as if a parent of this anon
|
||||
// const is an impl it will attempt to print out the impl trait ref
|
||||
// i.e. `<T as Trait>::{constant#0}`. This would cause printing to
|
||||
// enter an infinite recursion if the anon const is in the self type
|
||||
// i.e. `impl<T: Default> Default for [T; 32 - 1 - 1 - 1] {` where we
|
||||
// would try to print `<[T; /* print constant#0 again */] as //
|
||||
// Default>::{constant#0}`.
|
||||
write!(
|
||||
self,
|
||||
"{}::{}",
|
||||
|
|
@ -1742,7 +1749,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
self.tcx().try_get_global_alloc(prov.alloc_id())
|
||||
{
|
||||
self.typed_value(
|
||||
|this| this.print_value_path(instance.def_id(), instance.args),
|
||||
|this| this.pretty_print_value_path(instance.def_id(), instance.args),
|
||||
|this| this.print_type(ty),
|
||||
" as ",
|
||||
)?;
|
||||
|
|
@ -1936,7 +1943,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
let variant_idx =
|
||||
contents.variant.expect("destructed const of adt without variant idx");
|
||||
let variant_def = &def.variant(variant_idx);
|
||||
self.print_value_path(variant_def.def_id, args)?;
|
||||
self.pretty_print_value_path(variant_def.def_id, args)?;
|
||||
match variant_def.ctor_kind() {
|
||||
Some(CtorKind::Const) => {}
|
||||
Some(CtorKind::Fn) => {
|
||||
|
|
@ -1972,7 +1979,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
}
|
||||
(_, ty::FnDef(def_id, args)) => {
|
||||
// Never allowed today, but we still encounter them in invalid const args.
|
||||
self.print_value_path(def_id, args)?;
|
||||
self.pretty_print_value_path(def_id, args)?;
|
||||
return Ok(());
|
||||
}
|
||||
// FIXME(oli-obk): also pretty print arrays and other aggregate constants by reading
|
||||
|
|
@ -1993,7 +2000,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn pretty_closure_as_impl(
|
||||
fn pretty_print_closure_as_impl(
|
||||
&mut self,
|
||||
closure: ty::ClosureArgs<TyCtxt<'tcx>>,
|
||||
) -> Result<(), PrintError> {
|
||||
|
|
@ -2131,8 +2138,6 @@ impl<'a, 'tcx> FmtPrinter<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
// HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always
|
||||
// (but also some things just print a `DefId` generally so maybe we need this?)
|
||||
fn guess_def_namespace(tcx: TyCtxt<'_>, def_id: DefId) -> Namespace {
|
||||
match tcx.def_key(def_id).disambiguated_data.data {
|
||||
DefPathData::TypeNs(..) | DefPathData::CrateRoot | DefPathData::OpaqueTy => {
|
||||
|
|
@ -2157,6 +2162,7 @@ impl<'t> TyCtxt<'t> {
|
|||
self.def_path_str_with_args(def_id, &[])
|
||||
}
|
||||
|
||||
/// For this one we determine the appropriate namespace for the `def_id`.
|
||||
pub fn def_path_str_with_args(
|
||||
self,
|
||||
def_id: impl IntoQueryParam<DefId>,
|
||||
|
|
@ -2169,16 +2175,17 @@ impl<'t> TyCtxt<'t> {
|
|||
FmtPrinter::print_string(self, ns, |p| p.print_def_path(def_id, args)).unwrap()
|
||||
}
|
||||
|
||||
/// For this one we always use value namespace.
|
||||
pub fn value_path_str_with_args(
|
||||
self,
|
||||
def_id: impl IntoQueryParam<DefId>,
|
||||
args: &'t [GenericArg<'t>],
|
||||
) -> String {
|
||||
let def_id = def_id.into_query_param();
|
||||
let ns = guess_def_namespace(self, def_id);
|
||||
let ns = Namespace::ValueNS;
|
||||
debug!("value_path_str: def_id={:?}, ns={:?}", def_id, ns);
|
||||
|
||||
FmtPrinter::print_string(self, ns, |p| p.print_value_path(def_id, args)).unwrap()
|
||||
FmtPrinter::print_string(self, ns, |p| p.print_def_path(def_id, args)).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2230,7 +2237,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
|
|||
|
||||
self.print_def_path(parent_def_id, &[])?;
|
||||
|
||||
// HACK(eddyb) copy of `path_append` to avoid
|
||||
// HACK(eddyb) copy of `print_path_with_simple` to avoid
|
||||
// constructing a `DisambiguatedDefPathData`.
|
||||
if !self.empty_path {
|
||||
write!(self, "::")?;
|
||||
|
|
@ -2295,10 +2302,6 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn should_truncate(&mut self) -> bool {
|
||||
!self.type_length_limit.value_within_limit(self.printed_type_count)
|
||||
}
|
||||
|
||||
fn print_dyn_existential(
|
||||
&mut self,
|
||||
predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
||||
|
|
@ -2310,7 +2313,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
|
|||
self.pretty_print_const(ct, false)
|
||||
}
|
||||
|
||||
fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
|
||||
fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
|
||||
self.empty_path = true;
|
||||
if cnum == LOCAL_CRATE {
|
||||
if self.tcx.sess.at_least_rust_2018() {
|
||||
|
|
@ -2327,23 +2330,23 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn path_qualified(
|
||||
fn print_path_with_qualified(
|
||||
&mut self,
|
||||
self_ty: Ty<'tcx>,
|
||||
trait_ref: Option<ty::TraitRef<'tcx>>,
|
||||
) -> Result<(), PrintError> {
|
||||
self.pretty_path_qualified(self_ty, trait_ref)?;
|
||||
self.pretty_print_path_with_qualified(self_ty, trait_ref)?;
|
||||
self.empty_path = false;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn path_append_impl(
|
||||
fn print_path_with_impl(
|
||||
&mut self,
|
||||
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
|
||||
self_ty: Ty<'tcx>,
|
||||
trait_ref: Option<ty::TraitRef<'tcx>>,
|
||||
) -> Result<(), PrintError> {
|
||||
self.pretty_path_append_impl(
|
||||
self.pretty_print_path_with_impl(
|
||||
|p| {
|
||||
print_prefix(p)?;
|
||||
if !p.empty_path {
|
||||
|
|
@ -2359,7 +2362,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn path_append(
|
||||
fn print_path_with_simple(
|
||||
&mut self,
|
||||
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
|
||||
disambiguated_data: &DisambiguatedDefPathData,
|
||||
|
|
@ -2390,7 +2393,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn path_generic_args(
|
||||
fn print_path_with_generic_args(
|
||||
&mut self,
|
||||
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
|
||||
args: &[GenericArg<'tcx>],
|
||||
|
|
@ -2421,7 +2424,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
|
|||
self.0.const_infer_name_resolver.as_ref().and_then(|func| func(id))
|
||||
}
|
||||
|
||||
fn print_value_path(
|
||||
fn pretty_print_value_path(
|
||||
&mut self,
|
||||
def_id: DefId,
|
||||
args: &'tcx [GenericArg<'tcx>],
|
||||
|
|
@ -2433,7 +2436,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn print_in_binder<T>(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), PrintError>
|
||||
fn pretty_print_in_binder<T>(&mut self, value: &ty::Binder<'tcx, T>) -> Result<(), PrintError>
|
||||
where
|
||||
T: Print<'tcx, Self> + TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
|
|
@ -2487,6 +2490,10 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn should_truncate(&mut self) -> bool {
|
||||
!self.type_length_limit.value_within_limit(self.printed_type_count)
|
||||
}
|
||||
|
||||
fn should_print_region(&self, region: ty::Region<'tcx>) -> bool {
|
||||
let highlight = self.region_highlight_mode;
|
||||
if highlight.region_highlighted(region).is_some() {
|
||||
|
|
@ -2892,7 +2899,7 @@ where
|
|||
T: Print<'tcx, P> + TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
fn print(&self, p: &mut P) -> Result<(), PrintError> {
|
||||
p.print_in_binder(self)
|
||||
p.pretty_print_in_binder(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3090,7 +3097,7 @@ define_print! {
|
|||
}
|
||||
|
||||
write!(p, "fn")?;
|
||||
p.pretty_fn_sig(self.inputs(), self.c_variadic, self.output())?;
|
||||
p.pretty_print_fn_sig(self.inputs(), self.c_variadic, self.output())?;
|
||||
}
|
||||
|
||||
ty::TraitRef<'tcx> {
|
||||
|
|
@ -3225,7 +3232,7 @@ define_print! {
|
|||
// The args don't contain the self ty (as it has been erased) but the corresp.
|
||||
// generics do as the trait always has a self ty param. We need to offset.
|
||||
let args = &self.args[p.tcx().generics_of(self.def_id).parent_count - 1..];
|
||||
p.path_generic_args(|p| write!(p, "{name}"), args)?;
|
||||
p.print_path_with_generic_args(|p| write!(p, "{name}"), args)?;
|
||||
write!(p, " = ")?;
|
||||
self.term.print(p)?;
|
||||
}
|
||||
|
|
@ -3314,7 +3321,7 @@ define_print_and_forward_display! {
|
|||
}
|
||||
|
||||
PrintClosureAsImpl<'tcx> {
|
||||
p.pretty_closure_as_impl(self.closure)?;
|
||||
p.pretty_print_closure_as_impl(self.closure)?;
|
||||
}
|
||||
|
||||
ty::ParamTy {
|
||||
|
|
|
|||
|
|
@ -242,6 +242,9 @@ resolve_lowercase_self =
|
|||
attempt to use a non-constant value in a constant
|
||||
.suggestion = try using `Self`
|
||||
|
||||
resolve_macro_cannot_use_as_fn_like =
|
||||
`{$ident}` exists, but has no rules for function-like invocation
|
||||
|
||||
resolve_macro_cannot_use_as_attr =
|
||||
`{$ident}` exists, but has no `attr` rules
|
||||
|
||||
|
|
|
|||
|
|
@ -1232,7 +1232,8 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
|||
ItemKind::Fn(box ast::Fn { ident: fn_ident, .. }) => {
|
||||
match self.proc_macro_stub(item, *fn_ident) {
|
||||
Some((macro_kind, ident, span)) => {
|
||||
let res = Res::Def(DefKind::Macro(macro_kind), def_id.to_def_id());
|
||||
let macro_kinds = macro_kind.into();
|
||||
let res = Res::Def(DefKind::Macro(macro_kinds), def_id.to_def_id());
|
||||
let macro_data = MacroData::new(self.r.dummy_ext(macro_kind));
|
||||
self.r.new_local_macro(def_id, macro_data);
|
||||
self.r.proc_macro_stubs.insert(def_id);
|
||||
|
|
|
|||
|
|
@ -149,9 +149,9 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
|
|||
|
||||
let macro_data =
|
||||
self.resolver.compile_macro(def, *ident, &attrs, i.span, i.id, edition);
|
||||
let macro_kind = macro_data.ext.macro_kind();
|
||||
let macro_kinds = macro_data.ext.macro_kinds();
|
||||
opt_macro_data = Some(macro_data);
|
||||
DefKind::Macro(macro_kind)
|
||||
DefKind::Macro(macro_kinds)
|
||||
}
|
||||
ItemKind::GlobalAsm(..) => DefKind::GlobalAsm,
|
||||
ItemKind::Use(use_tree) => {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use rustc_errors::{
|
|||
use rustc_feature::BUILTIN_ATTRIBUTES;
|
||||
use rustc_hir::attrs::{AttributeKind, CfgEntry, StrippedCfgItem};
|
||||
use rustc_hir::def::Namespace::{self, *};
|
||||
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind, PerNS};
|
||||
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, MacroKinds, NonMacroAttrKind, PerNS};
|
||||
use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
|
||||
use rustc_hir::{PrimTy, Stability, StabilityLevel, find_attr};
|
||||
use rustc_middle::bug;
|
||||
|
|
@ -1491,11 +1491,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
let Some(binding) = resolution.borrow().best_binding() else {
|
||||
continue;
|
||||
};
|
||||
let Res::Def(DefKind::Macro(MacroKind::Derive | MacroKind::Attr), def_id) =
|
||||
binding.res()
|
||||
else {
|
||||
let Res::Def(DefKind::Macro(kinds), def_id) = binding.res() else {
|
||||
continue;
|
||||
};
|
||||
if !kinds.intersects(MacroKinds::ATTR | MacroKinds::DERIVE) {
|
||||
continue;
|
||||
}
|
||||
// By doing this all *imported* macros get added to the `macro_map` even if they
|
||||
// are *unused*, which makes the later suggestions find them and work.
|
||||
let _ = this.get_macro_by_def_id(def_id);
|
||||
|
|
@ -1504,7 +1505,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
},
|
||||
);
|
||||
|
||||
let is_expected = &|res: Res| res.macro_kind() == Some(macro_kind);
|
||||
let is_expected =
|
||||
&|res: Res| res.macro_kinds().is_some_and(|k| k.contains(macro_kind.into()));
|
||||
let suggestion = self.early_lookup_typo_candidate(
|
||||
ScopeSet::Macro(macro_kind),
|
||||
parent_scope,
|
||||
|
|
@ -1553,11 +1555,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
if let Some((def_id, unused_ident)) = unused_macro {
|
||||
let scope = self.local_macro_def_scopes[&def_id];
|
||||
let parent_nearest = parent_scope.module.nearest_parent_mod();
|
||||
if Some(parent_nearest) == scope.opt_def_id() {
|
||||
let unused_macro_kinds = self.local_macro_map[def_id].ext.macro_kinds();
|
||||
if !unused_macro_kinds.contains(macro_kind.into()) {
|
||||
match macro_kind {
|
||||
MacroKind::Bang => {
|
||||
err.subdiagnostic(MacroDefinedLater { span: unused_ident.span });
|
||||
err.subdiagnostic(MacroSuggMovePosition { span: ident.span, ident });
|
||||
err.subdiagnostic(MacroRulesNot::Func { span: unused_ident.span, ident });
|
||||
}
|
||||
MacroKind::Attr => {
|
||||
err.subdiagnostic(MacroRulesNot::Attr { span: unused_ident.span, ident });
|
||||
|
|
@ -1566,14 +1568,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
err.subdiagnostic(MacroRulesNot::Derive { span: unused_ident.span, ident });
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if self.macro_names.contains(&ident.normalize_to_macros_2_0()) {
|
||||
err.subdiagnostic(AddedMacroUse);
|
||||
return;
|
||||
if Some(parent_nearest) == scope.opt_def_id() {
|
||||
err.subdiagnostic(MacroDefinedLater { span: unused_ident.span });
|
||||
err.subdiagnostic(MacroSuggMovePosition { span: ident.span, ident });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ident.name == kw::Default
|
||||
|
|
@ -1601,13 +1602,18 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
};
|
||||
|
||||
let desc = match binding.res() {
|
||||
Res::Def(DefKind::Macro(MacroKind::Bang), _) => "a function-like macro".to_string(),
|
||||
Res::Def(DefKind::Macro(MacroKind::Attr), _) | Res::NonMacroAttr(..) => {
|
||||
Res::Def(DefKind::Macro(MacroKinds::BANG), _) => {
|
||||
"a function-like macro".to_string()
|
||||
}
|
||||
Res::Def(DefKind::Macro(MacroKinds::ATTR), _) | Res::NonMacroAttr(..) => {
|
||||
format!("an attribute: `#[{ident}]`")
|
||||
}
|
||||
Res::Def(DefKind::Macro(MacroKind::Derive), _) => {
|
||||
Res::Def(DefKind::Macro(MacroKinds::DERIVE), _) => {
|
||||
format!("a derive macro: `#[derive({ident})]`")
|
||||
}
|
||||
Res::Def(DefKind::Macro(kinds), _) => {
|
||||
format!("{} {}", kinds.article(), kinds.descr())
|
||||
}
|
||||
Res::ToolMod => {
|
||||
// Don't confuse the user with tool modules.
|
||||
continue;
|
||||
|
|
@ -1644,6 +1650,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
err.subdiagnostic(note);
|
||||
return;
|
||||
}
|
||||
|
||||
if self.macro_names.contains(&ident.normalize_to_macros_2_0()) {
|
||||
err.subdiagnostic(AddedMacroUse);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// Given an attribute macro that failed to be resolved, look for `derive` macros that could
|
||||
|
|
@ -2748,9 +2759,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
|
||||
let binding_key = BindingKey::new(ident, MacroNS);
|
||||
let binding = self.resolution(crate_module, binding_key)?.binding()?;
|
||||
let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() else {
|
||||
let Res::Def(DefKind::Macro(kinds), _) = binding.res() else {
|
||||
return None;
|
||||
};
|
||||
if !kinds.contains(MacroKinds::BANG) {
|
||||
return None;
|
||||
}
|
||||
let module_name = crate_module.kind.name().unwrap_or(kw::Crate);
|
||||
let import_snippet = match import.kind {
|
||||
ImportKind::Single { source, target, .. } if source != target => {
|
||||
|
|
|
|||
|
|
@ -672,6 +672,12 @@ pub(crate) struct MacroSuggMovePosition {
|
|||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum MacroRulesNot {
|
||||
#[label(resolve_macro_cannot_use_as_fn_like)]
|
||||
Func {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
ident: Ident,
|
||||
},
|
||||
#[label(resolve_macro_cannot_use_as_attr)]
|
||||
Attr {
|
||||
#[primary_span]
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use Determinacy::*;
|
|||
use Namespace::*;
|
||||
use rustc_ast::{self as ast, NodeId};
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir::def::{DefKind, Namespace, NonMacroAttrKind, PartialRes, PerNS};
|
||||
use rustc_hir::def::{DefKind, MacroKinds, Namespace, NonMacroAttrKind, PartialRes, PerNS};
|
||||
use rustc_middle::bug;
|
||||
use rustc_session::lint::BuiltinLintDiag;
|
||||
use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK;
|
||||
|
|
@ -259,7 +259,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
{
|
||||
let ext = &self.get_macro_by_def_id(def_id).ext;
|
||||
if ext.builtin_name.is_none()
|
||||
&& ext.macro_kind() == MacroKind::Derive
|
||||
&& ext.macro_kinds() == MacroKinds::DERIVE
|
||||
&& parent.expansion.outer_expn_is_descendant_of(*ctxt)
|
||||
{
|
||||
return Some((parent, derive_fallback_lint_id));
|
||||
|
|
@ -632,17 +632,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
|
||||
match result {
|
||||
Ok((binding, flags)) => {
|
||||
let binding_macro_kind = binding.macro_kind();
|
||||
// If we're looking for an attribute, that might be supported by a
|
||||
// `macro_rules!` macro.
|
||||
// FIXME: Replace this with tracking multiple macro kinds for one Def.
|
||||
if !(sub_namespace_match(binding_macro_kind, macro_kind)
|
||||
|| (binding_macro_kind == Some(MacroKind::Bang)
|
||||
&& macro_kind == Some(MacroKind::Attr)
|
||||
&& this
|
||||
.get_macro(binding.res())
|
||||
.is_some_and(|macro_data| macro_data.attr_ext.is_some())))
|
||||
{
|
||||
if !sub_namespace_match(binding.macro_kinds(), macro_kind) {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,14 +19,13 @@ use rustc_errors::{
|
|||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::Namespace::{self, *};
|
||||
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind};
|
||||
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, MacroKinds};
|
||||
use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
|
||||
use rustc_hir::{MissingLifetimeKind, PrimTy};
|
||||
use rustc_middle::ty;
|
||||
use rustc_session::{Session, lint};
|
||||
use rustc_span::edit_distance::{edit_distance, find_best_match_for_name};
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
|
||||
use thin_vec::ThinVec;
|
||||
use tracing::debug;
|
||||
|
|
@ -1850,12 +1849,12 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
|
||||
match (res, source) {
|
||||
(
|
||||
Res::Def(DefKind::Macro(MacroKind::Bang), def_id),
|
||||
Res::Def(DefKind::Macro(kinds), def_id),
|
||||
PathSource::Expr(Some(Expr {
|
||||
kind: ExprKind::Index(..) | ExprKind::Call(..), ..
|
||||
}))
|
||||
| PathSource::Struct(_),
|
||||
) => {
|
||||
) if kinds.contains(MacroKinds::BANG) => {
|
||||
// Don't suggest macro if it's unstable.
|
||||
let suggestable = def_id.is_local()
|
||||
|| self.r.tcx.lookup_stability(def_id).is_none_or(|s| s.is_stable());
|
||||
|
|
@ -1880,7 +1879,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
err.note("if you want the `try` keyword, you need Rust 2018 or later");
|
||||
}
|
||||
}
|
||||
(Res::Def(DefKind::Macro(MacroKind::Bang), _), _) => {
|
||||
(Res::Def(DefKind::Macro(kinds), _), _) if kinds.contains(MacroKinds::BANG) => {
|
||||
err.span_label(span, fallback_label.to_string());
|
||||
}
|
||||
(Res::Def(DefKind::TyAlias, def_id), PathSource::Trait(_)) => {
|
||||
|
|
|
|||
|
|
@ -53,7 +53,8 @@ use rustc_feature::BUILTIN_ATTRIBUTES;
|
|||
use rustc_hir::attrs::StrippedCfgItem;
|
||||
use rustc_hir::def::Namespace::{self, *};
|
||||
use rustc_hir::def::{
|
||||
self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS,
|
||||
self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, MacroKinds, NonMacroAttrKind, PartialRes,
|
||||
PerNS,
|
||||
};
|
||||
use rustc_hir::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap};
|
||||
use rustc_hir::definitions::DisambiguatorState;
|
||||
|
|
@ -969,8 +970,8 @@ impl<'ra> NameBindingData<'ra> {
|
|||
matches!(self.res(), Res::Def(DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy, _))
|
||||
}
|
||||
|
||||
fn macro_kind(&self) -> Option<MacroKind> {
|
||||
self.res().macro_kind()
|
||||
fn macro_kinds(&self) -> Option<MacroKinds> {
|
||||
self.res().macro_kinds()
|
||||
}
|
||||
|
||||
// Suppose that we resolved macro invocation with `invoc_parent_expansion` to binding `binding`
|
||||
|
|
@ -1030,14 +1031,13 @@ struct DeriveData {
|
|||
|
||||
struct MacroData {
|
||||
ext: Arc<SyntaxExtension>,
|
||||
attr_ext: Option<Arc<SyntaxExtension>>,
|
||||
nrules: usize,
|
||||
macro_rules: bool,
|
||||
}
|
||||
|
||||
impl MacroData {
|
||||
fn new(ext: Arc<SyntaxExtension>) -> MacroData {
|
||||
MacroData { ext, attr_ext: None, nrules: 0, macro_rules: false }
|
||||
MacroData { ext, nrules: 0, macro_rules: false }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
//! A bunch of methods and structures more or less related to resolving macros and
|
||||
//! interface provided by `Resolver` to macro expander.
|
||||
|
||||
use std::any::Any;
|
||||
use std::cell::Cell;
|
||||
use std::mem;
|
||||
use std::sync::Arc;
|
||||
|
|
@ -13,13 +12,13 @@ use rustc_expand::base::{
|
|||
Annotatable, DeriveResolution, Indeterminate, ResolverExpand, SyntaxExtension,
|
||||
SyntaxExtensionKind,
|
||||
};
|
||||
use rustc_expand::compile_declarative_macro;
|
||||
use rustc_expand::expand::{
|
||||
AstFragment, AstFragmentKind, Invocation, InvocationKind, SupportsMacroExpansion,
|
||||
};
|
||||
use rustc_expand::{MacroRulesMacroExpander, compile_declarative_macro};
|
||||
use rustc_hir::StabilityLevel;
|
||||
use rustc_hir::attrs::{CfgEntry, StrippedCfgItem};
|
||||
use rustc_hir::def::{self, DefKind, Namespace, NonMacroAttrKind};
|
||||
use rustc_hir::def::{self, DefKind, MacroKinds, Namespace, NonMacroAttrKind};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
|
||||
use rustc_middle::middle::stability;
|
||||
use rustc_middle::ty::{RegisteredTools, TyCtxt};
|
||||
|
|
@ -86,22 +85,19 @@ pub(crate) type MacroRulesScopeRef<'ra> = &'ra Cell<MacroRulesScope<'ra>>;
|
|||
/// one for attribute-like macros (attributes, derives).
|
||||
/// We ignore resolutions from one sub-namespace when searching names in scope for another.
|
||||
pub(crate) fn sub_namespace_match(
|
||||
candidate: Option<MacroKind>,
|
||||
candidate: Option<MacroKinds>,
|
||||
requirement: Option<MacroKind>,
|
||||
) -> bool {
|
||||
#[derive(PartialEq)]
|
||||
enum SubNS {
|
||||
Bang,
|
||||
AttrLike,
|
||||
}
|
||||
let sub_ns = |kind| match kind {
|
||||
MacroKind::Bang => SubNS::Bang,
|
||||
MacroKind::Attr | MacroKind::Derive => SubNS::AttrLike,
|
||||
};
|
||||
let candidate = candidate.map(sub_ns);
|
||||
let requirement = requirement.map(sub_ns);
|
||||
// "No specific sub-namespace" means "matches anything" for both requirements and candidates.
|
||||
candidate.is_none() || requirement.is_none() || candidate == requirement
|
||||
let (Some(candidate), Some(requirement)) = (candidate, requirement) else {
|
||||
return true;
|
||||
};
|
||||
match requirement {
|
||||
MacroKind::Bang => candidate.contains(MacroKinds::BANG),
|
||||
MacroKind::Attr | MacroKind::Derive => {
|
||||
candidate.intersects(MacroKinds::ATTR | MacroKinds::DERIVE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We don't want to format a path using pretty-printing,
|
||||
|
|
@ -323,6 +319,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
|
|||
parent_scope.expansion,
|
||||
span,
|
||||
fast_print_path(path),
|
||||
kind,
|
||||
def_id,
|
||||
def_id.map(|def_id| self.macro_def_scope(def_id).nearest_parent_mod()),
|
||||
),
|
||||
|
|
@ -356,11 +353,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
|
|||
}
|
||||
let def_id = self.local_def_id(node_id);
|
||||
let m = &self.local_macro_map[&def_id];
|
||||
let SyntaxExtensionKind::LegacyBang(ref ext) = m.ext.kind else {
|
||||
continue;
|
||||
};
|
||||
let ext: &dyn Any = ext.as_ref();
|
||||
let Some(m) = ext.downcast_ref::<MacroRulesMacroExpander>() else {
|
||||
let SyntaxExtensionKind::MacroRules(ref m) = m.ext.kind else {
|
||||
continue;
|
||||
};
|
||||
for arm_i in unused_arms.iter() {
|
||||
|
|
@ -633,7 +626,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
|
||||
self.check_stability_and_deprecation(&ext, path, node_id);
|
||||
|
||||
let unexpected_res = if ext.macro_kind() != kind {
|
||||
let unexpected_res = if !ext.macro_kinds().contains(kind.into()) {
|
||||
Some((kind.article(), kind.descr_expected()))
|
||||
} else if matches!(res, Res::Def(..)) {
|
||||
match supports_macro_expansion {
|
||||
|
|
@ -665,7 +658,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
// Suggest moving the macro out of the derive() if the macro isn't Derive
|
||||
if !path.span.from_expansion()
|
||||
&& kind == MacroKind::Derive
|
||||
&& ext.macro_kind() != MacroKind::Derive
|
||||
&& !ext.macro_kinds().contains(MacroKinds::DERIVE)
|
||||
&& ext.macro_kinds().contains(MacroKinds::ATTR)
|
||||
{
|
||||
err.remove_surrounding_derive = Some(RemoveSurroundingDerive { span: path.span });
|
||||
err.add_as_non_derive = Some(AddAsNonDerive { macro_path: &path_str });
|
||||
|
|
@ -842,10 +836,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
}
|
||||
_ => None,
|
||||
},
|
||||
None => self.get_macro(res).map(|macro_data| match kind {
|
||||
Some(MacroKind::Attr) if let Some(ref ext) = macro_data.attr_ext => Arc::clone(ext),
|
||||
_ => Arc::clone(¯o_data.ext),
|
||||
}),
|
||||
None => self.get_macro(res).map(|macro_data| Arc::clone(¯o_data.ext)),
|
||||
};
|
||||
Ok((ext, res))
|
||||
}
|
||||
|
|
@ -1114,7 +1105,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
&& let Some(binding) = binding
|
||||
// This is a `macro_rules` itself, not some import.
|
||||
&& let NameBindingKind::Res(res) = binding.kind
|
||||
&& let Res::Def(DefKind::Macro(MacroKind::Bang), def_id) = res
|
||||
&& let Res::Def(DefKind::Macro(kinds), def_id) = res
|
||||
&& kinds.contains(MacroKinds::BANG)
|
||||
// And the `macro_rules` is defined inside the attribute's module,
|
||||
// so it cannot be in scope unless imported.
|
||||
&& self.tcx.is_descendant_of(def_id, mod_def_id.to_def_id())
|
||||
|
|
@ -1161,8 +1153,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
// Reserve some names that are not quite covered by the general check
|
||||
// performed on `Resolver::builtin_attrs`.
|
||||
if ident.name == sym::cfg || ident.name == sym::cfg_attr {
|
||||
let macro_kind = self.get_macro(res).map(|macro_data| macro_data.ext.macro_kind());
|
||||
if macro_kind.is_some() && sub_namespace_match(macro_kind, Some(MacroKind::Attr)) {
|
||||
let macro_kinds = self.get_macro(res).map(|macro_data| macro_data.ext.macro_kinds());
|
||||
if macro_kinds.is_some() && sub_namespace_match(macro_kinds, Some(MacroKind::Attr)) {
|
||||
self.dcx()
|
||||
.emit_err(errors::NameReservedInAttributeNamespace { span: ident.span, ident });
|
||||
}
|
||||
|
|
@ -1181,7 +1173,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
node_id: NodeId,
|
||||
edition: Edition,
|
||||
) -> MacroData {
|
||||
let (mut ext, mut attr_ext, mut nrules) = compile_declarative_macro(
|
||||
let (mut ext, mut nrules) = compile_declarative_macro(
|
||||
self.tcx.sess,
|
||||
self.tcx.features(),
|
||||
macro_def,
|
||||
|
|
@ -1198,14 +1190,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
// The macro is a built-in, replace its expander function
|
||||
// while still taking everything else from the source code.
|
||||
ext.kind = builtin_ext_kind.clone();
|
||||
attr_ext = None;
|
||||
nrules = 0;
|
||||
} else {
|
||||
self.dcx().emit_err(errors::CannotFindBuiltinMacroWithName { span, ident });
|
||||
}
|
||||
}
|
||||
|
||||
MacroData { ext: Arc::new(ext), attr_ext, nrules, macro_rules: macro_def.macro_rules }
|
||||
MacroData { ext: Arc::new(ext), nrules, macro_rules: macro_def.macro_rules }
|
||||
}
|
||||
|
||||
fn path_accessible(
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ pub(super) fn mangle<'tcx>(
|
|||
|
||||
let hash = get_symbol_hash(tcx, instance, instance_ty, instantiating_crate);
|
||||
|
||||
let mut p = SymbolPrinter { tcx, path: SymbolPath::new(), keep_within_component: false };
|
||||
let mut p = LegacySymbolMangler { tcx, path: SymbolPath::new(), keep_within_component: false };
|
||||
p.print_def_path(
|
||||
def_id,
|
||||
if let ty::InstanceKind::DropGlue(_, _)
|
||||
|
|
@ -213,13 +213,13 @@ impl SymbolPath {
|
|||
}
|
||||
}
|
||||
|
||||
struct SymbolPrinter<'tcx> {
|
||||
struct LegacySymbolMangler<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
path: SymbolPath,
|
||||
|
||||
// When `true`, `finalize_pending_component` isn't used.
|
||||
// This is needed when recursing into `path_qualified`,
|
||||
// or `path_generic_args`, as any nested paths are
|
||||
// This is needed when recursing into `print_path_with_qualified`,
|
||||
// or `print_path_with_generic_args`, as any nested paths are
|
||||
// logically within one component.
|
||||
keep_within_component: bool,
|
||||
}
|
||||
|
|
@ -228,7 +228,7 @@ struct SymbolPrinter<'tcx> {
|
|||
// `PrettyPrinter` aka pretty printing of e.g. types in paths,
|
||||
// symbol names should have their own printing machinery.
|
||||
|
||||
impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> {
|
||||
impl<'tcx> Printer<'tcx> for LegacySymbolMangler<'tcx> {
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
|
@ -305,16 +305,17 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
|
||||
fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
|
||||
self.write_str(self.tcx.crate_name(cnum).as_str())?;
|
||||
Ok(())
|
||||
}
|
||||
fn path_qualified(
|
||||
|
||||
fn print_path_with_qualified(
|
||||
&mut self,
|
||||
self_ty: Ty<'tcx>,
|
||||
trait_ref: Option<ty::TraitRef<'tcx>>,
|
||||
) -> Result<(), PrintError> {
|
||||
// Similar to `pretty_path_qualified`, but for the other
|
||||
// Similar to `pretty_print_path_with_qualified`, but for the other
|
||||
// types that are printed as paths (see `print_type` above).
|
||||
match self_ty.kind() {
|
||||
ty::FnDef(..)
|
||||
|
|
@ -327,17 +328,17 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> {
|
|||
self.print_type(self_ty)
|
||||
}
|
||||
|
||||
_ => self.pretty_path_qualified(self_ty, trait_ref),
|
||||
_ => self.pretty_print_path_with_qualified(self_ty, trait_ref),
|
||||
}
|
||||
}
|
||||
|
||||
fn path_append_impl(
|
||||
fn print_path_with_impl(
|
||||
&mut self,
|
||||
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
|
||||
self_ty: Ty<'tcx>,
|
||||
trait_ref: Option<ty::TraitRef<'tcx>>,
|
||||
) -> Result<(), PrintError> {
|
||||
self.pretty_path_append_impl(
|
||||
self.pretty_print_path_with_impl(
|
||||
|cx| {
|
||||
print_prefix(cx)?;
|
||||
|
||||
|
|
@ -354,7 +355,8 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> {
|
|||
trait_ref,
|
||||
)
|
||||
}
|
||||
fn path_append(
|
||||
|
||||
fn print_path_with_simple(
|
||||
&mut self,
|
||||
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
|
||||
disambiguated_data: &DisambiguatedDefPathData,
|
||||
|
|
@ -377,7 +379,8 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
fn path_generic_args(
|
||||
|
||||
fn print_path_with_generic_args(
|
||||
&mut self,
|
||||
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
|
||||
args: &[GenericArg<'tcx>],
|
||||
|
|
@ -455,7 +458,7 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> PrettyPrinter<'tcx> for SymbolPrinter<'tcx> {
|
||||
impl<'tcx> PrettyPrinter<'tcx> for LegacySymbolMangler<'tcx> {
|
||||
fn should_print_region(&self, _region: ty::Region<'_>) -> bool {
|
||||
false
|
||||
}
|
||||
|
|
@ -491,7 +494,7 @@ impl<'tcx> PrettyPrinter<'tcx> for SymbolPrinter<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Write for SymbolPrinter<'_> {
|
||||
impl fmt::Write for LegacySymbolMangler<'_> {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
// Name sanitation. LLVM will happily accept identifiers with weird names, but
|
||||
// gas doesn't!
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ pub(super) fn mangle<'tcx>(
|
|||
let args = tcx.normalize_erasing_regions(ty::TypingEnv::fully_monomorphized(), instance.args);
|
||||
|
||||
let prefix = "_R";
|
||||
let mut p: SymbolMangler<'_> = SymbolMangler {
|
||||
let mut p: V0SymbolMangler<'_> = V0SymbolMangler {
|
||||
tcx,
|
||||
start_offset: prefix.len(),
|
||||
is_exportable,
|
||||
|
|
@ -88,7 +88,7 @@ pub fn mangle_internal_symbol<'tcx>(tcx: TyCtxt<'tcx>, item_name: &str) -> Strin
|
|||
}
|
||||
|
||||
let prefix = "_R";
|
||||
let mut p: SymbolMangler<'_> = SymbolMangler {
|
||||
let mut p: V0SymbolMangler<'_> = V0SymbolMangler {
|
||||
tcx,
|
||||
start_offset: prefix.len(),
|
||||
is_exportable: false,
|
||||
|
|
@ -131,7 +131,7 @@ pub(super) fn mangle_typeid_for_trait_ref<'tcx>(
|
|||
trait_ref: ty::ExistentialTraitRef<'tcx>,
|
||||
) -> String {
|
||||
// FIXME(flip1995): See comment in `mangle_typeid_for_fnabi`.
|
||||
let mut p = SymbolMangler {
|
||||
let mut p = V0SymbolMangler {
|
||||
tcx,
|
||||
start_offset: 0,
|
||||
is_exportable: false,
|
||||
|
|
@ -159,7 +159,7 @@ struct BinderLevel {
|
|||
lifetime_depths: Range<u32>,
|
||||
}
|
||||
|
||||
struct SymbolMangler<'tcx> {
|
||||
struct V0SymbolMangler<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
binders: Vec<BinderLevel>,
|
||||
out: String,
|
||||
|
|
@ -173,7 +173,7 @@ struct SymbolMangler<'tcx> {
|
|||
consts: FxHashMap<ty::Const<'tcx>, usize>,
|
||||
}
|
||||
|
||||
impl<'tcx> SymbolMangler<'tcx> {
|
||||
impl<'tcx> V0SymbolMangler<'tcx> {
|
||||
fn push(&mut self, s: &str) {
|
||||
self.out.push_str(s);
|
||||
}
|
||||
|
|
@ -272,7 +272,7 @@ impl<'tcx> SymbolMangler<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
|
||||
impl<'tcx> Printer<'tcx> for V0SymbolMangler<'tcx> {
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
|
@ -365,7 +365,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
|
|||
// Encode impl generic params if the generic parameters contain non-region parameters
|
||||
// and this isn't an inherent impl.
|
||||
if impl_trait_ref.is_some() && args.iter().any(|a| a.has_non_region_param()) {
|
||||
self.path_generic_args(
|
||||
self.print_path_with_generic_args(
|
||||
|this| {
|
||||
this.path_append_ns(
|
||||
|p| p.print_def_path(parent_def_id, &[]),
|
||||
|
|
@ -786,7 +786,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
|
|||
None => {
|
||||
self.push("S");
|
||||
for (field_def, field) in iter::zip(&variant_def.fields, fields) {
|
||||
// HACK(eddyb) this mimics `path_append`,
|
||||
// HACK(eddyb) this mimics `print_path_with_simple`,
|
||||
// instead of simply using `field_def.ident`,
|
||||
// just to be able to handle disambiguators.
|
||||
let disambiguated_field =
|
||||
|
|
@ -819,7 +819,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
|
||||
fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
|
||||
self.push("C");
|
||||
if !self.is_exportable {
|
||||
let stable_crate_id = self.tcx.def_path_hash(cnum.as_def_id()).stable_crate_id();
|
||||
|
|
@ -830,7 +830,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn path_qualified(
|
||||
fn print_path_with_qualified(
|
||||
&mut self,
|
||||
self_ty: Ty<'tcx>,
|
||||
trait_ref: Option<ty::TraitRef<'tcx>>,
|
||||
|
|
@ -843,7 +843,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
|
|||
self.print_def_path(trait_ref.def_id, trait_ref.args)
|
||||
}
|
||||
|
||||
fn path_append_impl(
|
||||
fn print_path_with_impl(
|
||||
&mut self,
|
||||
_: impl FnOnce(&mut Self) -> Result<(), PrintError>,
|
||||
_: Ty<'tcx>,
|
||||
|
|
@ -853,7 +853,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
|
|||
unreachable!()
|
||||
}
|
||||
|
||||
fn path_append(
|
||||
fn print_path_with_simple(
|
||||
&mut self,
|
||||
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
|
||||
disambiguated_data: &DisambiguatedDefPathData,
|
||||
|
|
@ -873,7 +873,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
|
|||
DefPathData::SyntheticCoroutineBody => 's',
|
||||
DefPathData::NestedStatic => 'n',
|
||||
|
||||
// These should never show up as `path_append` arguments.
|
||||
// These should never show up as `print_path_with_simple` arguments.
|
||||
DefPathData::CrateRoot
|
||||
| DefPathData::Use
|
||||
| DefPathData::GlobalAsm
|
||||
|
|
@ -896,7 +896,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
|
|||
)
|
||||
}
|
||||
|
||||
fn path_generic_args(
|
||||
fn print_path_with_generic_args(
|
||||
&mut self,
|
||||
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
|
||||
args: &[GenericArg<'tcx>],
|
||||
|
|
|
|||
|
|
@ -2147,6 +2147,7 @@ supported_targets! {
|
|||
|
||||
("aarch64-unknown-none", aarch64_unknown_none),
|
||||
("aarch64-unknown-none-softfloat", aarch64_unknown_none_softfloat),
|
||||
("aarch64_be-unknown-none-softfloat", aarch64_be_unknown_none_softfloat),
|
||||
("aarch64-unknown-nuttx", aarch64_unknown_nuttx),
|
||||
|
||||
("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
// Generic big-endian AArch64 target for bare-metal code - Floating point disabled
|
||||
//
|
||||
// Can be used in conjunction with the `target-feature` and
|
||||
// `target-cpu` compiler flags to opt-in more hardware-specific
|
||||
// features.
|
||||
//
|
||||
// For example, `-C target-cpu=cortex-a53`.
|
||||
use rustc_abi::Endian;
|
||||
|
||||
use crate::spec::{
|
||||
Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, StackProbeType, Target,
|
||||
TargetMetadata, TargetOptions,
|
||||
};
|
||||
|
||||
pub(crate) fn target() -> Target {
|
||||
let opts = TargetOptions {
|
||||
abi: "softfloat".into(),
|
||||
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
|
||||
linker: Some("rust-lld".into()),
|
||||
features: "+v8a,+strict-align,-neon,-fp-armv8".into(),
|
||||
relocation_model: RelocModel::Static,
|
||||
disable_redzone: true,
|
||||
max_atomic_width: Some(128),
|
||||
supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS,
|
||||
stack_probes: StackProbeType::Inline,
|
||||
panic_strategy: PanicStrategy::Abort,
|
||||
endian: Endian::Big,
|
||||
..Default::default()
|
||||
};
|
||||
Target {
|
||||
llvm_target: "aarch64_be-unknown-none".into(),
|
||||
metadata: TargetMetadata {
|
||||
description: Some("Bare ARM64 (big-endian), softfloat".into()),
|
||||
tier: Some(3),
|
||||
host_tools: Some(false),
|
||||
std: Some(false),
|
||||
},
|
||||
pointer_width: 64,
|
||||
data_layout: "E-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
|
||||
arch: "aarch64".into(),
|
||||
options: opts,
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ pub(crate) fn target() -> Target {
|
|||
host_tools: None,
|
||||
std: None,
|
||||
},
|
||||
data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8".into(),
|
||||
data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8:16-a:8".into(),
|
||||
llvm_target: "avr-unknown-unknown".into(),
|
||||
pointer_width: 16,
|
||||
options: TargetOptions {
|
||||
|
|
|
|||
|
|
@ -248,6 +248,10 @@ static AARCH64_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
|
|||
("mte", Stable, &[]),
|
||||
// FEAT_AdvSimd & FEAT_FP
|
||||
("neon", Stable, &[]),
|
||||
// Backend option to turn atomic operations into an intrinsic call when `lse` is not known to be
|
||||
// available, so the intrinsic can do runtime LSE feature detection rather than unconditionally
|
||||
// using slower non-LSE operations. Unstable since it doesn't need to user-togglable.
|
||||
("outline-atomics", Unstable(sym::aarch64_unstable_target_feature), &[]),
|
||||
// FEAT_PAUTH (address authentication)
|
||||
("paca", Stable, &[]),
|
||||
// FEAT_PAUTH (generic authentication)
|
||||
|
|
|
|||
|
|
@ -224,12 +224,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
use ty::GenericArg;
|
||||
use ty::print::Printer;
|
||||
|
||||
struct AbsolutePathPrinter<'tcx> {
|
||||
struct ConflictingPathPrinter<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
segments: Vec<Symbol>,
|
||||
}
|
||||
|
||||
impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
|
||||
impl<'tcx> Printer<'tcx> for ConflictingPathPrinter<'tcx> {
|
||||
fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
|
@ -253,12 +253,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
unreachable!(); // because `path_generic_args` ignores the `GenericArgs`
|
||||
}
|
||||
|
||||
fn path_crate(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
|
||||
fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError> {
|
||||
self.segments = vec![self.tcx.crate_name(cnum)];
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn path_qualified(
|
||||
fn print_path_with_qualified(
|
||||
&mut self,
|
||||
_self_ty: Ty<'tcx>,
|
||||
_trait_ref: Option<ty::TraitRef<'tcx>>,
|
||||
|
|
@ -266,7 +266,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
Err(fmt::Error)
|
||||
}
|
||||
|
||||
fn path_append_impl(
|
||||
fn print_path_with_impl(
|
||||
&mut self,
|
||||
_print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
|
||||
_self_ty: Ty<'tcx>,
|
||||
|
|
@ -275,7 +275,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
Err(fmt::Error)
|
||||
}
|
||||
|
||||
fn path_append(
|
||||
fn print_path_with_simple(
|
||||
&mut self,
|
||||
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
|
||||
disambiguated_data: &DisambiguatedDefPathData,
|
||||
|
|
@ -285,7 +285,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn path_generic_args(
|
||||
fn print_path_with_generic_args(
|
||||
&mut self,
|
||||
print_prefix: impl FnOnce(&mut Self) -> Result<(), PrintError>,
|
||||
_args: &[GenericArg<'tcx>],
|
||||
|
|
@ -300,28 +300,27 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
// let _ = [{struct Foo; Foo}, {struct Foo; Foo}];
|
||||
if did1.krate != did2.krate {
|
||||
let abs_path = |def_id| {
|
||||
let mut p = AbsolutePathPrinter { tcx: self.tcx, segments: vec![] };
|
||||
let mut p = ConflictingPathPrinter { tcx: self.tcx, segments: vec![] };
|
||||
p.print_def_path(def_id, &[]).map(|_| p.segments)
|
||||
};
|
||||
|
||||
// We compare strings because DefPath can be different
|
||||
// for imported and non-imported crates
|
||||
// We compare strings because DefPath can be different for imported and
|
||||
// non-imported crates.
|
||||
let expected_str = self.tcx.def_path_str(did1);
|
||||
let found_str = self.tcx.def_path_str(did2);
|
||||
let Ok(expected_abs) = abs_path(did1) else { return false };
|
||||
let Ok(found_abs) = abs_path(did2) else { return false };
|
||||
let same_path = || -> Result<_, PrintError> {
|
||||
Ok(expected_str == found_str || expected_abs == found_abs)
|
||||
};
|
||||
// We want to use as unique a type path as possible. If both types are "locally
|
||||
// known" by the same name, we use the "absolute path" which uses the original
|
||||
// crate name instead.
|
||||
let (expected, found) = if expected_str == found_str {
|
||||
(join_path_syms(&expected_abs), join_path_syms(&found_abs))
|
||||
} else {
|
||||
(expected_str.clone(), found_str.clone())
|
||||
};
|
||||
if same_path().unwrap_or(false) {
|
||||
let same_path = expected_str == found_str || expected_abs == found_abs;
|
||||
if same_path {
|
||||
// We want to use as unique a type path as possible. If both types are "locally
|
||||
// known" by the same name, we use the "absolute path" which uses the original
|
||||
// crate name instead.
|
||||
let (expected, found) = if expected_str == found_str {
|
||||
(join_path_syms(&expected_abs), join_path_syms(&found_abs))
|
||||
} else {
|
||||
(expected_str.clone(), found_str.clone())
|
||||
};
|
||||
|
||||
// We've displayed "expected `a::b`, found `a::b`". We add context to
|
||||
// differentiate the different cases where that might happen.
|
||||
let expected_crate_name = self.tcx.crate_name(did1.krate);
|
||||
|
|
|
|||
|
|
@ -946,7 +946,7 @@ fn foo(&self) -> Self::T { String::new() }
|
|||
|
||||
pub fn format_generic_args(&self, args: &[ty::GenericArg<'tcx>]) -> String {
|
||||
FmtPrinter::print_string(self.tcx, hir::def::Namespace::TypeNS, |p| {
|
||||
p.path_generic_args(|_| Ok(()), args)
|
||||
p.print_path_with_generic_args(|_| Ok(()), args)
|
||||
})
|
||||
.expect("could not write to `String`.")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,10 +12,11 @@
|
|||
//! The global cache has to be completely unobservable, while the per-cycle cache may impact
|
||||
//! behavior as long as the resulting behavior is still correct.
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::collections::{BTreeMap, btree_map};
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
use std::iter;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use derive_where::derive_where;
|
||||
|
|
@ -230,13 +231,19 @@ impl AvailableDepth {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
struct CycleHead {
|
||||
paths_to_head: PathsToNested,
|
||||
usage_kind: UsageKind,
|
||||
}
|
||||
|
||||
/// All cycle heads a given goal depends on, ordered by their stack depth.
|
||||
///
|
||||
/// We also track all paths from this goal to that head. This is necessary
|
||||
/// when rebasing provisional cache results.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct CycleHeads {
|
||||
heads: BTreeMap<StackDepth, PathsToNested>,
|
||||
heads: BTreeMap<StackDepth, CycleHead>,
|
||||
}
|
||||
|
||||
impl CycleHeads {
|
||||
|
|
@ -256,32 +263,32 @@ impl CycleHeads {
|
|||
self.heads.first_key_value().map(|(k, _)| *k)
|
||||
}
|
||||
|
||||
fn remove_highest_cycle_head(&mut self) -> PathsToNested {
|
||||
fn remove_highest_cycle_head(&mut self) -> CycleHead {
|
||||
let last = self.heads.pop_last();
|
||||
last.unwrap().1
|
||||
}
|
||||
|
||||
fn insert(&mut self, head: StackDepth, path_from_entry: impl Into<PathsToNested> + Copy) {
|
||||
*self.heads.entry(head).or_insert(path_from_entry.into()) |= path_from_entry.into();
|
||||
}
|
||||
|
||||
fn iter(&self) -> impl Iterator<Item = (StackDepth, PathsToNested)> + '_ {
|
||||
self.heads.iter().map(|(k, v)| (*k, *v))
|
||||
}
|
||||
|
||||
/// Update the cycle heads of a goal at depth `this` given the cycle heads
|
||||
/// of a nested goal. This merges the heads after filtering the parent goal
|
||||
/// itself.
|
||||
fn extend_from_child(&mut self, this: StackDepth, step_kind: PathKind, child: &CycleHeads) {
|
||||
for (&head, &path_from_entry) in child.heads.iter() {
|
||||
match head.cmp(&this) {
|
||||
Ordering::Less => {}
|
||||
Ordering::Equal => continue,
|
||||
Ordering::Greater => unreachable!(),
|
||||
fn insert(
|
||||
&mut self,
|
||||
head_index: StackDepth,
|
||||
path_from_entry: impl Into<PathsToNested> + Copy,
|
||||
usage_kind: UsageKind,
|
||||
) {
|
||||
match self.heads.entry(head_index) {
|
||||
btree_map::Entry::Vacant(entry) => {
|
||||
entry.insert(CycleHead { paths_to_head: path_from_entry.into(), usage_kind });
|
||||
}
|
||||
btree_map::Entry::Occupied(entry) => {
|
||||
let head = entry.into_mut();
|
||||
head.paths_to_head |= path_from_entry.into();
|
||||
head.usage_kind = head.usage_kind.merge(usage_kind);
|
||||
}
|
||||
self.insert(head, path_from_entry.extend_with(step_kind));
|
||||
}
|
||||
}
|
||||
|
||||
fn iter(&self) -> impl Iterator<Item = (StackDepth, CycleHead)> + '_ {
|
||||
self.heads.iter().map(|(k, v)| (*k, *v))
|
||||
}
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
|
|
@ -487,9 +494,6 @@ impl<X: Cx> EvaluationResult<X> {
|
|||
|
||||
pub struct SearchGraph<D: Delegate<Cx = X>, X: Cx = <D as Delegate>::Cx> {
|
||||
root_depth: AvailableDepth,
|
||||
/// The stack of goals currently being computed.
|
||||
///
|
||||
/// An element is *deeper* in the stack if its index is *lower*.
|
||||
stack: Stack<X>,
|
||||
/// The provisional cache contains entries for already computed goals which
|
||||
/// still depend on goals higher-up in the stack. We don't move them to the
|
||||
|
|
@ -511,6 +515,7 @@ pub struct SearchGraph<D: Delegate<Cx = X>, X: Cx = <D as Delegate>::Cx> {
|
|||
/// cache entry.
|
||||
enum UpdateParentGoalCtxt<'a, X: Cx> {
|
||||
Ordinary(&'a NestedGoals<X>),
|
||||
CycleOnStack(X::Input),
|
||||
ProvisionalCacheHit,
|
||||
}
|
||||
|
||||
|
|
@ -532,21 +537,42 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
|
|||
stack: &mut Stack<X>,
|
||||
step_kind_from_parent: PathKind,
|
||||
required_depth_for_nested: usize,
|
||||
heads: &CycleHeads,
|
||||
heads: impl Iterator<Item = (StackDepth, CycleHead)>,
|
||||
encountered_overflow: bool,
|
||||
context: UpdateParentGoalCtxt<'_, X>,
|
||||
) {
|
||||
if let Some(parent_index) = stack.last_index() {
|
||||
let parent = &mut stack[parent_index];
|
||||
if let Some((parent_index, parent)) = stack.last_mut_with_index() {
|
||||
parent.required_depth = parent.required_depth.max(required_depth_for_nested + 1);
|
||||
parent.encountered_overflow |= encountered_overflow;
|
||||
|
||||
parent.heads.extend_from_child(parent_index, step_kind_from_parent, heads);
|
||||
for (head_index, head) in heads {
|
||||
match head_index.cmp(&parent_index) {
|
||||
Ordering::Less => parent.heads.insert(
|
||||
head_index,
|
||||
head.paths_to_head.extend_with(step_kind_from_parent),
|
||||
head.usage_kind,
|
||||
),
|
||||
Ordering::Equal => {
|
||||
let usage_kind = parent
|
||||
.has_been_used
|
||||
.map_or(head.usage_kind, |prev| prev.merge(head.usage_kind));
|
||||
parent.has_been_used = Some(usage_kind);
|
||||
}
|
||||
Ordering::Greater => unreachable!(),
|
||||
}
|
||||
}
|
||||
let parent_depends_on_cycle = match context {
|
||||
UpdateParentGoalCtxt::Ordinary(nested_goals) => {
|
||||
parent.nested_goals.extend_from_child(step_kind_from_parent, nested_goals);
|
||||
!nested_goals.is_empty()
|
||||
}
|
||||
UpdateParentGoalCtxt::CycleOnStack(head) => {
|
||||
// We lookup provisional cache entries before detecting cycles.
|
||||
// We therefore can't use a global cache entry if it contains a cycle
|
||||
// whose head is in the provisional cache.
|
||||
parent.nested_goals.insert(head, step_kind_from_parent.into());
|
||||
true
|
||||
}
|
||||
UpdateParentGoalCtxt::ProvisionalCacheHit => true,
|
||||
};
|
||||
// Once we've got goals which encountered overflow or a cycle,
|
||||
|
|
@ -674,7 +700,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
|
|||
&mut self.stack,
|
||||
step_kind_from_parent,
|
||||
evaluation_result.required_depth,
|
||||
&evaluation_result.heads,
|
||||
evaluation_result.heads.iter(),
|
||||
evaluation_result.encountered_overflow,
|
||||
UpdateParentGoalCtxt::Ordinary(&evaluation_result.nested_goals),
|
||||
);
|
||||
|
|
@ -772,7 +798,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
|
|||
stack_entry: &StackEntry<X>,
|
||||
mut mutate_result: impl FnMut(X::Input, X::Result) -> X::Result,
|
||||
) {
|
||||
let popped_head = self.stack.next_index();
|
||||
let popped_head_index = self.stack.next_index();
|
||||
#[allow(rustc::potential_query_instability)]
|
||||
self.provisional_cache.retain(|&input, entries| {
|
||||
entries.retain_mut(|entry| {
|
||||
|
|
@ -782,7 +808,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
|
|||
path_from_head,
|
||||
result,
|
||||
} = entry;
|
||||
let ep = if heads.highest_cycle_head() == popped_head {
|
||||
let popped_head = if heads.highest_cycle_head() == popped_head_index {
|
||||
heads.remove_highest_cycle_head()
|
||||
} else {
|
||||
return true;
|
||||
|
|
@ -795,9 +821,14 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
|
|||
//
|
||||
// After rebasing the cycles `hph` will go through `e`. We need to make
|
||||
// sure that forall possible paths `hep`, `heph` is equal to `hph.`
|
||||
for (h, ph) in stack_entry.heads.iter() {
|
||||
let hp =
|
||||
Self::cycle_path_kind(&self.stack, stack_entry.step_kind_from_parent, h);
|
||||
let ep = popped_head.paths_to_head;
|
||||
for (head_index, head) in stack_entry.heads.iter() {
|
||||
let ph = head.paths_to_head;
|
||||
let hp = Self::cycle_path_kind(
|
||||
&self.stack,
|
||||
stack_entry.step_kind_from_parent,
|
||||
head_index,
|
||||
);
|
||||
|
||||
// We first validate that all cycles while computing `p` would stay
|
||||
// the same if we were to recompute it as a nested goal of `e`.
|
||||
|
|
@ -817,7 +848,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
|
|||
// the heads of `e` to make sure that rebasing `e` again also considers
|
||||
// them.
|
||||
let eph = ep.extend_with_paths(ph);
|
||||
heads.insert(h, eph);
|
||||
heads.insert(head_index, eph, head.usage_kind);
|
||||
}
|
||||
|
||||
let Some(head) = heads.opt_highest_cycle_head() else {
|
||||
|
|
@ -877,11 +908,10 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
|
|||
&mut self.stack,
|
||||
step_kind_from_parent,
|
||||
0,
|
||||
heads,
|
||||
heads.iter(),
|
||||
encountered_overflow,
|
||||
UpdateParentGoalCtxt::ProvisionalCacheHit,
|
||||
);
|
||||
debug_assert!(self.stack[head].has_been_used.is_some());
|
||||
debug!(?head, ?path_from_head, "provisional cache hit");
|
||||
return Some(result);
|
||||
}
|
||||
|
|
@ -993,12 +1023,12 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
|
|||
|
||||
// We don't move cycle participants to the global cache, so the
|
||||
// cycle heads are always empty.
|
||||
let heads = Default::default();
|
||||
let heads = iter::empty();
|
||||
Self::update_parent_goal(
|
||||
&mut self.stack,
|
||||
step_kind_from_parent,
|
||||
required_depth,
|
||||
&heads,
|
||||
heads,
|
||||
encountered_overflow,
|
||||
UpdateParentGoalCtxt::Ordinary(nested_goals),
|
||||
);
|
||||
|
|
@ -1014,34 +1044,31 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
|
|||
input: X::Input,
|
||||
step_kind_from_parent: PathKind,
|
||||
) -> Option<X::Result> {
|
||||
let head = self.stack.find(input)?;
|
||||
let head_index = self.stack.find(input)?;
|
||||
// We have a nested goal which directly relies on a goal deeper in the stack.
|
||||
//
|
||||
// We start by tagging all cycle participants, as that's necessary for caching.
|
||||
//
|
||||
// Finally we can return either the provisional response or the initial response
|
||||
// in case we're in the first fixpoint iteration for this goal.
|
||||
let path_kind = Self::cycle_path_kind(&self.stack, step_kind_from_parent, head);
|
||||
debug!(?path_kind, "encountered cycle with depth {head:?}");
|
||||
let usage_kind = UsageKind::Single(path_kind);
|
||||
self.stack[head].has_been_used =
|
||||
Some(self.stack[head].has_been_used.map_or(usage_kind, |prev| prev.merge(usage_kind)));
|
||||
|
||||
// Subtle: when encountering a cyclic goal, we still first checked for overflow,
|
||||
// so we have to update the reached depth.
|
||||
let last_index = self.stack.last_index().unwrap();
|
||||
let last = &mut self.stack[last_index];
|
||||
last.required_depth = last.required_depth.max(1);
|
||||
|
||||
last.nested_goals.insert(input, step_kind_from_parent.into());
|
||||
last.nested_goals.insert(last.input, PathsToNested::EMPTY);
|
||||
if last_index != head {
|
||||
last.heads.insert(head, step_kind_from_parent);
|
||||
}
|
||||
let path_kind = Self::cycle_path_kind(&self.stack, step_kind_from_parent, head_index);
|
||||
debug!(?path_kind, "encountered cycle with depth {head_index:?}");
|
||||
let head = CycleHead {
|
||||
paths_to_head: step_kind_from_parent.into(),
|
||||
usage_kind: UsageKind::Single(path_kind),
|
||||
};
|
||||
Self::update_parent_goal(
|
||||
&mut self.stack,
|
||||
step_kind_from_parent,
|
||||
0,
|
||||
iter::once((head_index, head)),
|
||||
false,
|
||||
UpdateParentGoalCtxt::CycleOnStack(input),
|
||||
);
|
||||
|
||||
// Return the provisional result or, if we're in the first iteration,
|
||||
// start with no constraints.
|
||||
if let Some(result) = self.stack[head].provisional_result {
|
||||
if let Some(result) = self.stack[head_index].provisional_result {
|
||||
Some(result)
|
||||
} else {
|
||||
Some(D::initial_provisional_result(cx, path_kind, input))
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use std::ops::{Index, IndexMut};
|
||||
use std::ops::Index;
|
||||
|
||||
use derive_where::derive_where;
|
||||
use rustc_index::IndexVec;
|
||||
|
|
@ -48,6 +48,12 @@ pub(super) struct StackEntry<X: Cx> {
|
|||
pub nested_goals: NestedGoals<X>,
|
||||
}
|
||||
|
||||
/// The stack of goals currently being computed.
|
||||
///
|
||||
/// An element is *deeper* in the stack if its index is *lower*.
|
||||
///
|
||||
/// Only the last entry of the stack is mutable. All other entries get
|
||||
/// lazily updated in `update_parent_goal`.
|
||||
#[derive_where(Default; X: Cx)]
|
||||
pub(super) struct Stack<X: Cx> {
|
||||
entries: IndexVec<StackDepth, StackEntry<X>>,
|
||||
|
|
@ -62,10 +68,6 @@ impl<X: Cx> Stack<X> {
|
|||
self.entries.len()
|
||||
}
|
||||
|
||||
pub(super) fn last_index(&self) -> Option<StackDepth> {
|
||||
self.entries.last_index()
|
||||
}
|
||||
|
||||
pub(super) fn last(&self) -> Option<&StackEntry<X>> {
|
||||
self.entries.raw.last()
|
||||
}
|
||||
|
|
@ -74,6 +76,10 @@ impl<X: Cx> Stack<X> {
|
|||
self.entries.raw.last_mut()
|
||||
}
|
||||
|
||||
pub(super) fn last_mut_with_index(&mut self) -> Option<(StackDepth, &mut StackEntry<X>)> {
|
||||
self.entries.last_index().map(|idx| (idx, &mut self.entries[idx]))
|
||||
}
|
||||
|
||||
pub(super) fn next_index(&self) -> StackDepth {
|
||||
self.entries.next_index()
|
||||
}
|
||||
|
|
@ -108,9 +114,3 @@ impl<X: Cx> Index<StackDepth> for Stack<X> {
|
|||
&self.entries[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl<X: Cx> IndexMut<StackDepth> for Stack<X> {
|
||||
fn index_mut(&mut self, index: StackDepth) -> &mut Self::Output {
|
||||
&mut self.entries[index]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ use serde_derive::Deserialize;
|
|||
#[cfg(feature = "tracing")]
|
||||
use tracing::{instrument, span};
|
||||
|
||||
use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags};
|
||||
use crate::core::build_steps::gcc::{Gcc, GccOutput, add_cg_gcc_cargo_flags};
|
||||
use crate::core::build_steps::tool::{RustcPrivateCompilers, SourceType, copy_lld_artifacts};
|
||||
use crate::core::build_steps::{dist, llvm};
|
||||
use crate::core::builder;
|
||||
|
|
@ -1543,13 +1543,22 @@ impl Step for RustcLink {
|
|||
}
|
||||
}
|
||||
|
||||
/// Output of the `compile::GccCodegenBackend` step.
|
||||
/// It includes the path to the libgccjit library on which this backend depends.
|
||||
#[derive(Clone)]
|
||||
pub struct GccCodegenBackendOutput {
|
||||
stamp: BuildStamp,
|
||||
gcc: GccOutput,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct GccCodegenBackend {
|
||||
compilers: RustcPrivateCompilers,
|
||||
}
|
||||
|
||||
impl Step for GccCodegenBackend {
|
||||
type Output = BuildStamp;
|
||||
type Output = GccCodegenBackendOutput;
|
||||
|
||||
const ONLY_HOSTS: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
|
|
@ -1584,6 +1593,8 @@ impl Step for GccCodegenBackend {
|
|||
&CodegenBackendKind::Gcc,
|
||||
);
|
||||
|
||||
let gcc = builder.ensure(Gcc { target });
|
||||
|
||||
if builder.config.keep_stage.contains(&build_compiler.stage) {
|
||||
trace!("`keep-stage` requested");
|
||||
builder.info(
|
||||
|
|
@ -1592,7 +1603,7 @@ impl Step for GccCodegenBackend {
|
|||
);
|
||||
// Codegen backends are linked separately from this step today, so we don't do
|
||||
// anything here.
|
||||
return stamp;
|
||||
return GccCodegenBackendOutput { stamp, gcc };
|
||||
}
|
||||
|
||||
let mut cargo = builder::Cargo::new(
|
||||
|
|
@ -1606,13 +1617,16 @@ impl Step for GccCodegenBackend {
|
|||
cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
|
||||
rustc_cargo_env(builder, &mut cargo, target);
|
||||
|
||||
let gcc = builder.ensure(Gcc { target });
|
||||
add_cg_gcc_cargo_flags(&mut cargo, &gcc);
|
||||
|
||||
let _guard =
|
||||
builder.msg(Kind::Build, "codegen backend gcc", Mode::Codegen, build_compiler, target);
|
||||
let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
|
||||
write_codegen_backend_stamp(stamp, files, builder.config.dry_run())
|
||||
|
||||
GccCodegenBackendOutput {
|
||||
stamp: write_codegen_backend_stamp(stamp, files, builder.config.dry_run()),
|
||||
gcc,
|
||||
}
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Option<StepMetadata> {
|
||||
|
|
@ -2191,53 +2205,6 @@ impl Step for Assemble {
|
|||
);
|
||||
build_compiler.stage = actual_stage;
|
||||
|
||||
let mut codegen_backend_stamps = vec![];
|
||||
{
|
||||
#[cfg(feature = "tracing")]
|
||||
let _codegen_backend_span =
|
||||
span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
|
||||
|
||||
for backend in builder.config.enabled_codegen_backends(target_compiler.host) {
|
||||
// FIXME: this is a horrible hack used to make `x check` work when other codegen
|
||||
// backends are enabled.
|
||||
// `x check` will check stage 1 rustc, which copies its rmetas to the stage0 sysroot.
|
||||
// Then it checks codegen backends, which correctly use these rmetas.
|
||||
// Then it needs to check std, but for that it needs to build stage 1 rustc.
|
||||
// This copies the build rmetas into the stage0 sysroot, effectively poisoning it,
|
||||
// because we then have both check and build rmetas in the same sysroot.
|
||||
// That would be fine on its own. However, when another codegen backend is enabled,
|
||||
// then building stage 1 rustc implies also building stage 1 codegen backend (even if
|
||||
// it isn't used for anything). And since that tries to use the poisoned
|
||||
// rmetas, it fails to build.
|
||||
// We don't actually need to build rustc-private codegen backends for checking std,
|
||||
// so instead we skip that.
|
||||
// Note: this would be also an issue for other rustc-private tools, but that is "solved"
|
||||
// by check::Std being last in the list of checked things (see
|
||||
// `Builder::get_step_descriptions`).
|
||||
if builder.kind == Kind::Check && builder.top_stage == 1 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let prepare_compilers = || {
|
||||
RustcPrivateCompilers::from_build_and_target_compiler(
|
||||
build_compiler,
|
||||
target_compiler,
|
||||
)
|
||||
};
|
||||
|
||||
let stamp = match backend {
|
||||
CodegenBackendKind::Cranelift => {
|
||||
builder.ensure(CraneliftCodegenBackend { compilers: prepare_compilers() })
|
||||
}
|
||||
CodegenBackendKind::Gcc => {
|
||||
builder.ensure(GccCodegenBackend { compilers: prepare_compilers() })
|
||||
}
|
||||
CodegenBackendKind::Llvm | CodegenBackendKind::Custom(_) => continue,
|
||||
};
|
||||
codegen_backend_stamps.push(stamp);
|
||||
}
|
||||
}
|
||||
|
||||
let stage = target_compiler.stage;
|
||||
let host = target_compiler.host;
|
||||
let (host_info, dir_name) = if build_compiler.host == host {
|
||||
|
|
@ -2296,9 +2263,56 @@ impl Step for Assemble {
|
|||
}
|
||||
}
|
||||
|
||||
debug!("copying codegen backends to sysroot");
|
||||
for stamp in codegen_backend_stamps {
|
||||
copy_codegen_backends_to_sysroot(builder, stamp, target_compiler);
|
||||
{
|
||||
#[cfg(feature = "tracing")]
|
||||
let _codegen_backend_span =
|
||||
span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
|
||||
|
||||
for backend in builder.config.enabled_codegen_backends(target_compiler.host) {
|
||||
// FIXME: this is a horrible hack used to make `x check` work when other codegen
|
||||
// backends are enabled.
|
||||
// `x check` will check stage 1 rustc, which copies its rmetas to the stage0 sysroot.
|
||||
// Then it checks codegen backends, which correctly use these rmetas.
|
||||
// Then it needs to check std, but for that it needs to build stage 1 rustc.
|
||||
// This copies the build rmetas into the stage0 sysroot, effectively poisoning it,
|
||||
// because we then have both check and build rmetas in the same sysroot.
|
||||
// That would be fine on its own. However, when another codegen backend is enabled,
|
||||
// then building stage 1 rustc implies also building stage 1 codegen backend (even if
|
||||
// it isn't used for anything). And since that tries to use the poisoned
|
||||
// rmetas, it fails to build.
|
||||
// We don't actually need to build rustc-private codegen backends for checking std,
|
||||
// so instead we skip that.
|
||||
// Note: this would be also an issue for other rustc-private tools, but that is "solved"
|
||||
// by check::Std being last in the list of checked things (see
|
||||
// `Builder::get_step_descriptions`).
|
||||
if builder.kind == Kind::Check && builder.top_stage == 1 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let prepare_compilers = || {
|
||||
RustcPrivateCompilers::from_build_and_target_compiler(
|
||||
build_compiler,
|
||||
target_compiler,
|
||||
)
|
||||
};
|
||||
|
||||
match backend {
|
||||
CodegenBackendKind::Cranelift => {
|
||||
let stamp = builder
|
||||
.ensure(CraneliftCodegenBackend { compilers: prepare_compilers() });
|
||||
copy_codegen_backends_to_sysroot(builder, stamp, target_compiler);
|
||||
}
|
||||
CodegenBackendKind::Gcc => {
|
||||
let output =
|
||||
builder.ensure(GccCodegenBackend { compilers: prepare_compilers() });
|
||||
copy_codegen_backends_to_sysroot(builder, output.stamp, target_compiler);
|
||||
// Also copy libgccjit to the library sysroot, so that it is available for
|
||||
// the codegen backend.
|
||||
output.gcc.install_to(builder, &rustc_libdir);
|
||||
}
|
||||
CodegenBackendKind::Llvm | CodegenBackendKind::Custom(_) => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if builder.config.lld_enabled {
|
||||
|
|
|
|||
|
|
@ -478,7 +478,19 @@ impl Step for Rustc {
|
|||
if libdir_relative.to_str() != Some("bin") {
|
||||
let libdir = builder.rustc_libdir(compiler);
|
||||
for entry in builder.read_dir(&libdir) {
|
||||
if is_dylib(&entry.path()) {
|
||||
// A safeguard that we will not ship libgccjit.so from the libdir, in case the
|
||||
// GCC codegen backend is enabled by default.
|
||||
// Long-term we should probably split the config options for:
|
||||
// - Include cg_gcc in the rustc sysroot by default
|
||||
// - Run dist of a specific codegen backend in `x dist` by default
|
||||
if is_dylib(&entry.path())
|
||||
&& !entry
|
||||
.path()
|
||||
.file_name()
|
||||
.and_then(|n| n.to_str())
|
||||
.map(|n| n.contains("libgccjit"))
|
||||
.unwrap_or(false)
|
||||
{
|
||||
// Don't use custom libdir here because ^lib/ will be resolved again
|
||||
// with installer
|
||||
builder.install(&entry.path(), &image.join("lib"), FileType::NativeLibrary);
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use std::fs;
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use crate::FileType;
|
||||
use crate::core::builder::{Builder, Cargo, Kind, RunConfig, ShouldRun, Step};
|
||||
use crate::core::config::TargetSelection;
|
||||
use crate::utils::build_stamp::{BuildStamp, generate_smart_stamp_hash};
|
||||
|
|
@ -28,6 +29,21 @@ pub struct GccOutput {
|
|||
pub libgccjit: PathBuf,
|
||||
}
|
||||
|
||||
impl GccOutput {
|
||||
/// Install the required libgccjit library file(s) to the specified `path`.
|
||||
pub fn install_to(&self, builder: &Builder<'_>, directory: &Path) {
|
||||
// At build time, cg_gcc has to link to libgccjit.so (the unversioned symbol).
|
||||
// However, at runtime, it will by default look for libgccjit.so.0.
|
||||
// So when we install the built libgccjit.so file to the target `directory`, we add it there
|
||||
// with the `.0` suffix.
|
||||
let mut target_filename = self.libgccjit.file_name().unwrap().to_str().unwrap().to_string();
|
||||
target_filename.push_str(".0");
|
||||
|
||||
let dst = directory.join(target_filename);
|
||||
builder.copy_link(&self.libgccjit, &dst, FileType::NativeLibrary);
|
||||
}
|
||||
}
|
||||
|
||||
impl Step for Gcc {
|
||||
type Output = GccOutput;
|
||||
|
||||
|
|
@ -61,7 +77,6 @@ impl Step for Gcc {
|
|||
}
|
||||
|
||||
build_gcc(&metadata, builder, target);
|
||||
create_lib_alias(builder, &libgccjit_path);
|
||||
|
||||
t!(metadata.stamp.write());
|
||||
|
||||
|
|
@ -69,15 +84,6 @@ impl Step for Gcc {
|
|||
}
|
||||
}
|
||||
|
||||
/// Creates a libgccjit.so.0 alias next to libgccjit.so if it does not
|
||||
/// already exist
|
||||
fn create_lib_alias(builder: &Builder<'_>, libgccjit: &PathBuf) {
|
||||
let lib_alias = libgccjit.parent().unwrap().join("libgccjit.so.0");
|
||||
if !lib_alias.exists() {
|
||||
t!(builder.symlink_file(libgccjit, lib_alias));
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Meta {
|
||||
stamp: BuildStamp,
|
||||
out_dir: PathBuf,
|
||||
|
|
@ -124,7 +130,6 @@ fn try_download_gcc(builder: &Builder<'_>, target: TargetSelection) -> Option<Pa
|
|||
}
|
||||
|
||||
let libgccjit = root.join("lib").join("libgccjit.so");
|
||||
create_lib_alias(builder, &libgccjit);
|
||||
Some(libgccjit)
|
||||
}
|
||||
PathFreshness::HasLocalModifications { .. } => {
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ pub struct Finder {
|
|||
const STAGE0_MISSING_TARGETS: &[&str] = &[
|
||||
"armv7a-vex-v5",
|
||||
// just a dummy comment so the list doesn't get onelined
|
||||
"aarch64_be-unknown-none-softfloat",
|
||||
];
|
||||
|
||||
/// Minimum version threshold for libstdc++ required when using prebuilt LLVM
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
- [\*-apple-visionos](platform-support/apple-visionos.md)
|
||||
- [aarch64-nintendo-switch-freestanding](platform-support/aarch64-nintendo-switch-freestanding.md)
|
||||
- [aarch64-unknown-linux-musl](platform-support/aarch64-unknown-linux-musl.md)
|
||||
- [aarch64_be-unknown-none-softfloat](platform-support/aarch64_be-unknown-none-softfloat.md)
|
||||
- [amdgcn-amd-amdhsa](platform-support/amdgcn-amd-amdhsa.md)
|
||||
- [armeb-unknown-linux-gnueabi](platform-support/armeb-unknown-linux-gnueabi.md)
|
||||
- [arm-none-eabi](platform-support/arm-none-eabi.md)
|
||||
|
|
|
|||
|
|
@ -273,6 +273,7 @@ target | std | host | notes
|
|||
`aarch64_be-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (big-endian)
|
||||
`aarch64_be-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (big-endian, ILP32 ABI)
|
||||
[`aarch64_be-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD (big-endian)
|
||||
[`aarch64_be-unknown-none-softfloat`](platform-support/aarch64_be-unknown-none-softfloat.md) | * | | Bare big-endian ARM64, softfloat
|
||||
[`amdgcn-amd-amdhsa`](platform-support/amdgcn-amd-amdhsa.md) | * | | `-Ctarget-cpu=gfx...` to specify [the AMD GPU] to compile for
|
||||
[`arm64_32-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | Arm Apple WatchOS 64-bit with 32-bit pointers
|
||||
[`arm64e-apple-darwin`](platform-support/arm64e-apple-darwin.md) | ✓ | ✓ | ARM64e Apple Darwin
|
||||
|
|
|
|||
|
|
@ -0,0 +1,74 @@
|
|||
# aarch64_be-unknown-none-softfloat
|
||||
|
||||
**Tier: 3**
|
||||
|
||||
Target for freestanding/bare-metal big-endian ARM64 binaries in ELF format:
|
||||
firmware, kernels, etc.
|
||||
|
||||
## Target maintainers
|
||||
|
||||
[@Gelbpunkt](https://github.com/Gelbpunkt)
|
||||
|
||||
## Requirements
|
||||
|
||||
This target is cross-compiled. There is no support for `std`. There is no
|
||||
default allocator, but it's possible to use `alloc` by supplying an allocator.
|
||||
|
||||
The target does not assume existence of a FPU and does not make use of any
|
||||
non-GPR register. This allows the generated code to run in environments, such
|
||||
as kernels, which may need to avoid the use of such registers or which may have
|
||||
special considerations about the use of such registers (e.g. saving and
|
||||
restoring them to avoid breaking userspace code using the same registers). You
|
||||
can change code generation to use additional CPU features via the
|
||||
`-C target-feature=` codegen options to rustc, or via the `#[target_feature]`
|
||||
mechanism within Rust code.
|
||||
|
||||
By default, code generated with the soft-float target should run on any
|
||||
big-endian ARM64 hardware, enabling additional target features may raise this
|
||||
baseline.
|
||||
|
||||
`extern "C"` uses the [architecture's standard calling convention][aapcs64].
|
||||
|
||||
[aapcs64]: https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst
|
||||
|
||||
The targets generate binaries in the ELF format. Any alternate formats or
|
||||
special considerations for binary layout will require linker options or linker
|
||||
scripts.
|
||||
|
||||
## Building the target
|
||||
|
||||
You can build Rust with support for the target by adding it to the `target`
|
||||
list in `bootstrap.toml`:
|
||||
|
||||
```toml
|
||||
[build]
|
||||
target = ["aarch64_be-unknown-none-softfloat"]
|
||||
```
|
||||
|
||||
## Building Rust programs
|
||||
|
||||
Rust does not yet ship pre-compiled artifacts for this target. To compile for
|
||||
this target, you will first need to build Rust with the target enabled (see
|
||||
"Building the target" above).
|
||||
|
||||
## Cross-compilation
|
||||
|
||||
For cross builds, you will need an appropriate ARM64 C/C++ toolchain for
|
||||
linking, or if you want to compile C code along with Rust (such as for Rust
|
||||
crates with C dependencies).
|
||||
|
||||
Rust *may* be able to use an `aarch64_be-unknown-linux-{gnu,musl}-` toolchain
|
||||
with appropriate standalone flags to build for this target (depending on the
|
||||
assumptions of that toolchain, see below), or you may wish to use a separate
|
||||
`aarch64_be-unknown-none-softfloat` toolchain.
|
||||
|
||||
On some ARM64 hosts that use ELF binaries, you *may* be able to use the host C
|
||||
toolchain, if it does not introduce assumptions about the host environment that
|
||||
don't match the expectations of a standalone environment. Otherwise, you may
|
||||
need a separate toolchain for standalone/freestanding development, just as when
|
||||
cross-compiling from a non-ARM64 platform.
|
||||
|
||||
## Testing
|
||||
|
||||
As the target supports a variety of different environments and does not support
|
||||
`std`, it does not support running the Rust test suite.
|
||||
|
|
@ -191,6 +191,20 @@ We can document it by escaping the initial `#`:
|
|||
/// ## bar # baz";
|
||||
```
|
||||
|
||||
Here is an example with a macro rule which matches on tokens starting with `#`:
|
||||
|
||||
`````rust,no_run
|
||||
/// ```
|
||||
/// macro_rules! ignore { (##tag) => {}; }
|
||||
/// ignore! {
|
||||
/// ###tag
|
||||
/// }
|
||||
/// ```
|
||||
# fn f() {}
|
||||
`````
|
||||
|
||||
As you can see, the rule is expecting two `#`, so when calling it, we need to add an extra `#`
|
||||
because the first one is used as escape.
|
||||
|
||||
## Using `?` in doc tests
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use std::sync::Arc;
|
|||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::Mutability;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def::{DefKind, MacroKinds, Res};
|
||||
use rustc_hir::def_id::{DefId, DefIdSet, LocalDefId, LocalModDefId};
|
||||
use rustc_metadata::creader::{CStore, LoadedMacro};
|
||||
use rustc_middle::ty::fast_reject::SimplifiedType;
|
||||
|
|
@ -137,13 +137,16 @@ pub(crate) fn try_inline(
|
|||
clean::ConstantItem(Box::new(ct))
|
||||
})
|
||||
}
|
||||
Res::Def(DefKind::Macro(kind), did) => {
|
||||
let mac = build_macro(cx, did, name, kind);
|
||||
Res::Def(DefKind::Macro(kinds), did) => {
|
||||
let mac = build_macro(cx, did, name, kinds);
|
||||
|
||||
let type_kind = match kind {
|
||||
MacroKind::Bang => ItemType::Macro,
|
||||
MacroKind::Attr => ItemType::ProcAttribute,
|
||||
MacroKind::Derive => ItemType::ProcDerive,
|
||||
// FIXME: handle attributes and derives that aren't proc macros, and macros with
|
||||
// multiple kinds
|
||||
let type_kind = match kinds {
|
||||
MacroKinds::BANG => ItemType::Macro,
|
||||
MacroKinds::ATTR => ItemType::ProcAttribute,
|
||||
MacroKinds::DERIVE => ItemType::ProcDerive,
|
||||
_ => todo!("Handle macros with multiple kinds"),
|
||||
};
|
||||
record_extern_fqn(cx, did, type_kind);
|
||||
mac
|
||||
|
|
@ -749,22 +752,36 @@ fn build_macro(
|
|||
cx: &mut DocContext<'_>,
|
||||
def_id: DefId,
|
||||
name: Symbol,
|
||||
macro_kind: MacroKind,
|
||||
macro_kinds: MacroKinds,
|
||||
) -> clean::ItemKind {
|
||||
match CStore::from_tcx(cx.tcx).load_macro_untracked(def_id, cx.tcx) {
|
||||
LoadedMacro::MacroDef { def, .. } => match macro_kind {
|
||||
MacroKind::Bang => clean::MacroItem(clean::Macro {
|
||||
// FIXME: handle attributes and derives that aren't proc macros, and macros with multiple
|
||||
// kinds
|
||||
LoadedMacro::MacroDef { def, .. } => match macro_kinds {
|
||||
MacroKinds::BANG => clean::MacroItem(clean::Macro {
|
||||
source: utils::display_macro_source(cx, name, &def),
|
||||
macro_rules: def.macro_rules,
|
||||
}),
|
||||
MacroKind::Derive | MacroKind::Attr => {
|
||||
clean::ProcMacroItem(clean::ProcMacro { kind: macro_kind, helpers: Vec::new() })
|
||||
}
|
||||
MacroKinds::DERIVE => clean::ProcMacroItem(clean::ProcMacro {
|
||||
kind: MacroKind::Derive,
|
||||
helpers: Vec::new(),
|
||||
}),
|
||||
MacroKinds::ATTR => clean::ProcMacroItem(clean::ProcMacro {
|
||||
kind: MacroKind::Attr,
|
||||
helpers: Vec::new(),
|
||||
}),
|
||||
_ => todo!("Handle macros with multiple kinds"),
|
||||
},
|
||||
LoadedMacro::ProcMacro(ext) => clean::ProcMacroItem(clean::ProcMacro {
|
||||
kind: ext.macro_kind(),
|
||||
helpers: ext.helper_attrs,
|
||||
}),
|
||||
LoadedMacro::ProcMacro(ext) => {
|
||||
// Proc macros can only have a single kind
|
||||
let kind = match ext.macro_kinds() {
|
||||
MacroKinds::BANG => MacroKind::Bang,
|
||||
MacroKinds::ATTR => MacroKind::Attr,
|
||||
MacroKinds::DERIVE => MacroKind::Derive,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
clean::ProcMacroItem(clean::ProcMacro { kind, helpers: ext.helper_attrs })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, In
|
|||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{FatalError, struct_span_code_err};
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
use rustc_hir::def::{CtorKind, DefKind, MacroKinds, Res};
|
||||
use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE, LocalDefId};
|
||||
use rustc_hir::{LangItem, PredicateOrigin, find_attr};
|
||||
use rustc_hir_analysis::hir_ty_lowering::FeedConstTy;
|
||||
|
|
@ -2845,11 +2845,19 @@ fn clean_maybe_renamed_item<'tcx>(
|
|||
generics: clean_generics(generics, cx),
|
||||
fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(),
|
||||
}),
|
||||
ItemKind::Macro(_, macro_def, MacroKind::Bang) => MacroItem(Macro {
|
||||
// FIXME: handle attributes and derives that aren't proc macros, and macros with
|
||||
// multiple kinds
|
||||
ItemKind::Macro(_, macro_def, MacroKinds::BANG) => MacroItem(Macro {
|
||||
source: display_macro_source(cx, name, macro_def),
|
||||
macro_rules: macro_def.macro_rules,
|
||||
}),
|
||||
ItemKind::Macro(_, _, macro_kind) => clean_proc_macro(item, &mut name, macro_kind, cx),
|
||||
ItemKind::Macro(_, _, MacroKinds::ATTR) => {
|
||||
clean_proc_macro(item, &mut name, MacroKind::Attr, cx)
|
||||
}
|
||||
ItemKind::Macro(_, _, MacroKinds::DERIVE) => {
|
||||
clean_proc_macro(item, &mut name, MacroKind::Derive, cx)
|
||||
}
|
||||
ItemKind::Macro(_, _, _) => todo!("Handle macros with multiple kinds"),
|
||||
// proc macros can have a name set by attributes
|
||||
ItemKind::Fn { ref sig, generics, body: body_id, .. } => {
|
||||
clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use std::fmt;
|
||||
|
||||
use rustc_hir::def::{CtorOf, DefKind};
|
||||
use rustc_hir::def::{CtorOf, DefKind, MacroKinds};
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
use serde::{Serialize, Serializer};
|
||||
|
||||
|
|
@ -134,9 +134,10 @@ impl ItemType {
|
|||
DefKind::Trait => Self::Trait,
|
||||
DefKind::TyAlias => Self::TypeAlias,
|
||||
DefKind::TraitAlias => Self::TraitAlias,
|
||||
DefKind::Macro(MacroKind::Bang) => ItemType::Macro,
|
||||
DefKind::Macro(MacroKind::Attr) => ItemType::ProcAttribute,
|
||||
DefKind::Macro(MacroKind::Derive) => ItemType::ProcDerive,
|
||||
DefKind::Macro(MacroKinds::BANG) => ItemType::Macro,
|
||||
DefKind::Macro(MacroKinds::ATTR) => ItemType::ProcAttribute,
|
||||
DefKind::Macro(MacroKinds::DERIVE) => ItemType::ProcDerive,
|
||||
DefKind::Macro(_) => todo!("Handle macros with multiple kinds"),
|
||||
DefKind::ForeignTy => Self::ForeignType,
|
||||
DefKind::Variant => Self::Variant,
|
||||
DefKind::Field => Self::StructField,
|
||||
|
|
|
|||
|
|
@ -2060,7 +2060,9 @@ class DocSearch {
|
|||
// Deprecated and unstable items and items with no description
|
||||
this.searchIndexDeprecated.set(crate, new RoaringBitmap(crateCorpus.c));
|
||||
this.searchIndexEmptyDesc.set(crate, new RoaringBitmap(crateCorpus.e));
|
||||
this.searchIndexUnstable.set(crate, new RoaringBitmap(crateCorpus.u));
|
||||
if (crateCorpus.u !== undefined && crateCorpus.u !== null) {
|
||||
this.searchIndexUnstable.set(crate, new RoaringBitmap(crateCorpus.u));
|
||||
}
|
||||
let descIndex = 0;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
|
|||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_errors::{Applicability, Diag, DiagMessage};
|
||||
use rustc_hir::def::Namespace::*;
|
||||
use rustc_hir::def::{DefKind, Namespace, PerNS};
|
||||
use rustc_hir::def::{DefKind, MacroKinds, Namespace, PerNS};
|
||||
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE};
|
||||
use rustc_hir::{Mutability, Safety};
|
||||
use rustc_middle::ty::{Ty, TyCtxt};
|
||||
|
|
@ -25,7 +25,6 @@ use rustc_resolve::rustdoc::{
|
|||
use rustc_session::config::CrateType;
|
||||
use rustc_session::lint::Lint;
|
||||
use rustc_span::BytePos;
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
use rustc_span::symbol::{Ident, Symbol, sym};
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use tracing::{debug, info, instrument, trace};
|
||||
|
|
@ -115,9 +114,11 @@ impl Res {
|
|||
|
||||
let prefix = match kind {
|
||||
DefKind::Fn | DefKind::AssocFn => return Suggestion::Function,
|
||||
DefKind::Macro(MacroKind::Bang) => return Suggestion::Macro,
|
||||
// FIXME: handle macros with multiple kinds, and attribute/derive macros that aren't
|
||||
// proc macros
|
||||
DefKind::Macro(MacroKinds::BANG) => return Suggestion::Macro,
|
||||
|
||||
DefKind::Macro(MacroKind::Derive) => "derive",
|
||||
DefKind::Macro(MacroKinds::DERIVE) => "derive",
|
||||
DefKind::Struct => "struct",
|
||||
DefKind::Enum => "enum",
|
||||
DefKind::Trait => "trait",
|
||||
|
|
@ -881,9 +882,12 @@ fn trait_impls_for<'a>(
|
|||
fn is_derive_trait_collision<T>(ns: &PerNS<Result<Vec<(Res, T)>, ResolutionFailure<'_>>>) -> bool {
|
||||
if let (Ok(type_ns), Ok(macro_ns)) = (&ns.type_ns, &ns.macro_ns) {
|
||||
type_ns.iter().any(|(res, _)| matches!(res, Res::Def(DefKind::Trait, _)))
|
||||
&& macro_ns
|
||||
.iter()
|
||||
.any(|(res, _)| matches!(res, Res::Def(DefKind::Macro(MacroKind::Derive), _)))
|
||||
&& macro_ns.iter().any(|(res, _)| {
|
||||
matches!(
|
||||
res,
|
||||
Res::Def(DefKind::Macro(kinds), _) if kinds.contains(MacroKinds::DERIVE)
|
||||
)
|
||||
})
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
|
@ -1674,11 +1678,11 @@ impl Disambiguator {
|
|||
|
||||
let suffixes = [
|
||||
// If you update this list, please also update the relevant rustdoc book section!
|
||||
("!()", DefKind::Macro(MacroKind::Bang)),
|
||||
("!{}", DefKind::Macro(MacroKind::Bang)),
|
||||
("![]", DefKind::Macro(MacroKind::Bang)),
|
||||
("!()", DefKind::Macro(MacroKinds::BANG)),
|
||||
("!{}", DefKind::Macro(MacroKinds::BANG)),
|
||||
("![]", DefKind::Macro(MacroKinds::BANG)),
|
||||
("()", DefKind::Fn),
|
||||
("!", DefKind::Macro(MacroKind::Bang)),
|
||||
("!", DefKind::Macro(MacroKinds::BANG)),
|
||||
];
|
||||
|
||||
if let Some(idx) = link.find('@') {
|
||||
|
|
@ -1697,7 +1701,7 @@ impl Disambiguator {
|
|||
safety: Safety::Safe,
|
||||
}),
|
||||
"function" | "fn" | "method" => Kind(DefKind::Fn),
|
||||
"derive" => Kind(DefKind::Macro(MacroKind::Derive)),
|
||||
"derive" => Kind(DefKind::Macro(MacroKinds::DERIVE)),
|
||||
"field" => Kind(DefKind::Field),
|
||||
"variant" => Kind(DefKind::Variant),
|
||||
"type" => NS(Namespace::TypeNS),
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use std::mem;
|
|||
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def::{DefKind, MacroKinds, Res};
|
||||
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LocalDefIdSet};
|
||||
use rustc_hir::intravisit::{Visitor, walk_body, walk_item};
|
||||
use rustc_hir::{CRATE_HIR_ID, Node};
|
||||
|
|
@ -13,7 +13,6 @@ use rustc_middle::hir::nested_filter;
|
|||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
use rustc_span::symbol::{Symbol, kw, sym};
|
||||
use tracing::debug;
|
||||
|
||||
|
|
@ -325,7 +324,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||
|
||||
let is_bang_macro = matches!(
|
||||
item,
|
||||
Node::Item(&hir::Item { kind: hir::ItemKind::Macro(_, _, MacroKind::Bang), .. })
|
||||
Node::Item(&hir::Item { kind: hir::ItemKind::Macro(_, _, kinds), .. }) if kinds.contains(MacroKinds::BANG)
|
||||
);
|
||||
|
||||
if !self.view_item_stack.insert(res_did) && !is_bang_macro {
|
||||
|
|
@ -406,7 +405,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||
// attribute can still be visible.
|
||||
|| match item.kind {
|
||||
hir::ItemKind::Impl(..) => true,
|
||||
hir::ItemKind::Macro(_, _, MacroKind::Bang) => {
|
||||
hir::ItemKind::Macro(_, _, _) => {
|
||||
self.cx.tcx.has_attr(item.owner_id.def_id, sym::macro_export)
|
||||
}
|
||||
_ => false,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ use rustc_data_structures::fx::FxHashSet;
|
|||
use rustc_hir::{EnumDef, FieldDef, Item, ItemKind, OwnerId, QPath, TyKind, Variant, VariantData};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::MacroKind;
|
||||
use rustc_span::symbol::Symbol;
|
||||
|
||||
declare_clippy_lint! {
|
||||
|
|
@ -503,8 +502,8 @@ impl LateLintPass<'_> for ItemNameRepetitions {
|
|||
);
|
||||
}
|
||||
|
||||
let is_macro_rule = matches!(item.kind, ItemKind::Macro(_, _, MacroKind::Bang));
|
||||
if both_are_public && item_camel.len() > mod_camel.len() && !is_macro_rule {
|
||||
let is_macro = matches!(item.kind, ItemKind::Macro(_, _, _));
|
||||
if both_are_public && item_camel.len() > mod_camel.len() && !is_macro {
|
||||
let matching = count_match_start(mod_camel, &item_camel);
|
||||
let rmatching = count_match_end(mod_camel, &item_camel);
|
||||
let nchars = mod_camel.chars().count();
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ use rustc_lint::{LateContext, LateLintPass};
|
|||
use rustc_middle::ty;
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::def_id::CRATE_DEF_ID;
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -89,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
|
|||
// We ignore macro exports. And `ListStem` uses, which aren't interesting.
|
||||
fn is_ignorable_export<'tcx>(item: &'tcx Item<'tcx>) -> bool {
|
||||
if let ItemKind::Use(path, kind) = item.kind {
|
||||
let ignore = matches!(path.res.macro_ns, Some(Res::Def(DefKind::Macro(MacroKind::Bang), _)))
|
||||
let ignore = matches!(path.res.macro_ns, Some(Res::Def(DefKind::Macro(_), _)))
|
||||
|| kind == UseKind::ListStem;
|
||||
if ignore {
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,10 @@
|
|||
use std::sync::atomic::AtomicI32;
|
||||
use std::sync::atomic::Ordering::*;
|
||||
|
||||
// Verify config on outline-atomics works (it is always enabled on aarch64-linux).
|
||||
#[cfg(not(target_feature = "outline-atomics"))]
|
||||
compile_error!("outline-atomics is not enabled");
|
||||
|
||||
pub fn compare_exchange(a: &AtomicI32) {
|
||||
// On AArch64 LLVM should outline atomic operations.
|
||||
// CHECK: __aarch64_cas4_relax
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@
|
|||
//@ revisions: aarch64_be_unknown_netbsd
|
||||
//@ [aarch64_be_unknown_netbsd] compile-flags: --target aarch64_be-unknown-netbsd
|
||||
//@ [aarch64_be_unknown_netbsd] needs-llvm-components: aarch64
|
||||
//@ revisions: aarch64_be_unknown_none_softfloat
|
||||
//@ [aarch64_be_unknown_none_softfloat] compile-flags: --target aarch64_be-unknown-none-softfloat
|
||||
//@ [aarch64_be_unknown_none_softfloat] needs-llvm-components: aarch64
|
||||
//@ revisions: aarch64_kmc_solid_asp3
|
||||
//@ [aarch64_kmc_solid_asp3] compile-flags: --target aarch64-kmc-solid_asp3
|
||||
//@ [aarch64_kmc_solid_asp3] needs-llvm-components: aarch64
|
||||
|
|
|
|||
|
|
@ -183,6 +183,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
|
|||
`nnp-assist`
|
||||
`nontrapping-fptoint`
|
||||
`nvic`
|
||||
`outline-atomics`
|
||||
`paca`
|
||||
`pacg`
|
||||
`pan`
|
||||
|
|
|
|||
|
|
@ -7,9 +7,46 @@ macro_rules! local_attr {
|
|||
//~^^ ERROR: local_attr
|
||||
}
|
||||
|
||||
//~v NOTE: `fn_only` exists, but has no `attr` rules
|
||||
macro_rules! fn_only {
|
||||
{} => {}
|
||||
}
|
||||
|
||||
//~v NOTE: `attr_only` exists, but has no rules for function-like invocation
|
||||
macro_rules! attr_only {
|
||||
attr() {} => {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
//~v NOTE: in this expansion of #[local_attr]
|
||||
#[local_attr]
|
||||
struct S;
|
||||
|
||||
local_attr!(arg); //~ ERROR: macro has no rules for function-like invocation
|
||||
//~vv ERROR: cannot find macro `local_attr` in this scope
|
||||
//~| NOTE: `local_attr` is in scope, but it is an attribute
|
||||
local_attr!(arg);
|
||||
|
||||
//~v ERROR: cannot find attribute `fn_only` in this scope
|
||||
#[fn_only]
|
||||
struct S;
|
||||
|
||||
attr_only!(); //~ ERROR: cannot find macro `attr_only` in this scope
|
||||
}
|
||||
|
||||
//~vv ERROR: cannot find attribute `forward_referenced_attr` in this scope
|
||||
//~| NOTE: consider moving the definition of `forward_referenced_attr` before this call
|
||||
#[forward_referenced_attr]
|
||||
struct S;
|
||||
|
||||
//~v NOTE: a macro with the same name exists, but it appears later
|
||||
macro_rules! forward_referenced_attr {
|
||||
attr() {} => {}
|
||||
}
|
||||
|
||||
//~vv ERROR: cannot find attribute `cyclic_attr` in this scope
|
||||
//~| NOTE: consider moving the definition of `cyclic_attr` before this call
|
||||
#[cyclic_attr]
|
||||
//~v NOTE: a macro with the same name exists, but it appears later
|
||||
macro_rules! cyclic_attr {
|
||||
attr() {} => {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,14 +9,55 @@ LL | #[local_attr]
|
|||
|
|
||||
= note: this error originates in the attribute macro `local_attr` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: macro has no rules for function-like invocation `local_attr!`
|
||||
--> $DIR/macro-rules-attr-error.rs:14:5
|
||||
error: cannot find macro `local_attr` in this scope
|
||||
--> $DIR/macro-rules-attr-error.rs:27:5
|
||||
|
|
||||
LL | macro_rules! local_attr {
|
||||
| ----------------------- this macro has no rules for function-like invocation
|
||||
...
|
||||
LL | local_attr!(arg);
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: `local_attr` is in scope, but it is an attribute: `#[local_attr]`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: cannot find attribute `fn_only` in this scope
|
||||
--> $DIR/macro-rules-attr-error.rs:30:7
|
||||
|
|
||||
LL | macro_rules! fn_only {
|
||||
| ------- `fn_only` exists, but has no `attr` rules
|
||||
...
|
||||
LL | #[fn_only]
|
||||
| ^^^^^^^
|
||||
|
||||
error: cannot find macro `attr_only` in this scope
|
||||
--> $DIR/macro-rules-attr-error.rs:33:5
|
||||
|
|
||||
LL | macro_rules! attr_only {
|
||||
| --------- `attr_only` exists, but has no rules for function-like invocation
|
||||
...
|
||||
LL | attr_only!();
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: cannot find attribute `forward_referenced_attr` in this scope
|
||||
--> $DIR/macro-rules-attr-error.rs:38:3
|
||||
|
|
||||
LL | #[forward_referenced_attr]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ consider moving the definition of `forward_referenced_attr` before this call
|
||||
|
|
||||
note: a macro with the same name exists, but it appears later
|
||||
--> $DIR/macro-rules-attr-error.rs:42:14
|
||||
|
|
||||
LL | macro_rules! forward_referenced_attr {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: cannot find attribute `cyclic_attr` in this scope
|
||||
--> $DIR/macro-rules-attr-error.rs:48:3
|
||||
|
|
||||
LL | #[cyclic_attr]
|
||||
| ^^^^^^^^^^^ consider moving the definition of `cyclic_attr` before this call
|
||||
|
|
||||
note: a macro with the same name exists, but it appears later
|
||||
--> $DIR/macro-rules-attr-error.rs:50:14
|
||||
|
|
||||
LL | macro_rules! cyclic_attr {
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -95,14 +95,6 @@ error: expected derive macro, found macro `crate::my_macro`
|
|||
|
|
||||
LL | #[derive(crate::my_macro)]
|
||||
| ^^^^^^^^^^^^^^^ not a derive macro
|
||||
|
|
||||
help: remove from the surrounding `derive()`
|
||||
--> $DIR/macro-namespace-reserved-2.rs:50:10
|
||||
|
|
||||
LL | #[derive(crate::my_macro)]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
= help: add as non-Derive macro
|
||||
`#[crate::my_macro]`
|
||||
|
||||
error: cannot find macro `my_macro_attr` in this scope
|
||||
--> $DIR/macro-namespace-reserved-2.rs:28:5
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue