Auto merge of #137446 - matthiaskrgr:rollup-16moy6v, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #135501 (Inject `compiler_builtins` during postprocessing and ensure it is made private) - #137121 (stabilize `(const_)ptr_sub_ptr`) - #137180 (Give `global_asm` a fake body to store typeck results, represent `sym fn` as a hir expr to fix `sym fn` operands with lifetimes) - #137256 (compiler: untangle SIMD alignment assumptions) - #137383 (stabilize `unsigned_is_multiple_of`) - #137415 (Remove invalid suggestion of into_iter for extern macro) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
bca5f37cbd
94 changed files with 704 additions and 539 deletions
|
|
@ -57,7 +57,7 @@ impl Reg {
|
|||
128 => dl.f128_align.abi,
|
||||
_ => panic!("unsupported float: {self:?}"),
|
||||
},
|
||||
RegKind::Vector => dl.vector_align(self.size).abi,
|
||||
RegKind::Vector => dl.llvmlike_vector_align(self.size).abi,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -310,10 +310,10 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
|
|||
let mut align = if repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align };
|
||||
let mut max_repr_align = repr.align;
|
||||
|
||||
// If all the non-ZST fields have the same ABI and union ABI optimizations aren't
|
||||
// disabled, we can use that common ABI for the union as a whole.
|
||||
// If all the non-ZST fields have the same repr and union repr optimizations aren't
|
||||
// disabled, we can use that common repr for the union as a whole.
|
||||
struct AbiMismatch;
|
||||
let mut common_non_zst_abi_and_align = if repr.inhibits_union_abi_opt() {
|
||||
let mut common_non_zst_repr_and_align = if repr.inhibits_union_abi_opt() {
|
||||
// Can't optimize
|
||||
Err(AbiMismatch)
|
||||
} else {
|
||||
|
|
@ -337,14 +337,14 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
|
|||
continue;
|
||||
}
|
||||
|
||||
if let Ok(common) = common_non_zst_abi_and_align {
|
||||
if let Ok(common) = common_non_zst_repr_and_align {
|
||||
// Discard valid range information and allow undef
|
||||
let field_abi = field.backend_repr.to_union();
|
||||
|
||||
if let Some((common_abi, common_align)) = common {
|
||||
if common_abi != field_abi {
|
||||
// Different fields have different ABI: disable opt
|
||||
common_non_zst_abi_and_align = Err(AbiMismatch);
|
||||
common_non_zst_repr_and_align = Err(AbiMismatch);
|
||||
} else {
|
||||
// Fields with the same non-Aggregate ABI should also
|
||||
// have the same alignment
|
||||
|
|
@ -357,7 +357,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
|
|||
}
|
||||
} else {
|
||||
// First non-ZST field: record its ABI and alignment
|
||||
common_non_zst_abi_and_align = Ok(Some((field_abi, field.align.abi)));
|
||||
common_non_zst_repr_and_align = Ok(Some((field_abi, field.align.abi)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -376,16 +376,25 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
|
|||
|
||||
// If all non-ZST fields have the same ABI, we may forward that ABI
|
||||
// for the union as a whole, unless otherwise inhibited.
|
||||
let abi = match common_non_zst_abi_and_align {
|
||||
let backend_repr = match common_non_zst_repr_and_align {
|
||||
Err(AbiMismatch) | Ok(None) => BackendRepr::Memory { sized: true },
|
||||
Ok(Some((abi, _))) => {
|
||||
if abi.inherent_align(dl).map(|a| a.abi) != Some(align.abi) {
|
||||
// Mismatched alignment (e.g. union is #[repr(packed)]): disable opt
|
||||
Ok(Some((repr, _))) => match repr {
|
||||
// Mismatched alignment (e.g. union is #[repr(packed)]): disable opt
|
||||
BackendRepr::Scalar(_) | BackendRepr::ScalarPair(_, _)
|
||||
if repr.scalar_align(dl).unwrap() != align.abi =>
|
||||
{
|
||||
BackendRepr::Memory { sized: true }
|
||||
} else {
|
||||
abi
|
||||
}
|
||||
}
|
||||
// Vectors require at least element alignment, else disable the opt
|
||||
BackendRepr::Vector { element, count: _ } if element.align(dl).abi > align.abi => {
|
||||
BackendRepr::Memory { sized: true }
|
||||
}
|
||||
// the alignment tests passed and we can use this
|
||||
BackendRepr::Scalar(..)
|
||||
| BackendRepr::ScalarPair(..)
|
||||
| BackendRepr::Vector { .. }
|
||||
| BackendRepr::Memory { .. } => repr,
|
||||
},
|
||||
};
|
||||
|
||||
let Some(union_field_count) = NonZeroUsize::new(only_variant.len()) else {
|
||||
|
|
@ -400,7 +409,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
|
|||
Ok(LayoutData {
|
||||
variants: Variants::Single { index: only_variant_idx },
|
||||
fields: FieldsShape::Union(union_field_count),
|
||||
backend_repr: abi,
|
||||
backend_repr,
|
||||
largest_niche: None,
|
||||
uninhabited: false,
|
||||
align,
|
||||
|
|
|
|||
|
|
@ -408,16 +408,21 @@ impl TargetDataLayout {
|
|||
}
|
||||
}
|
||||
|
||||
/// psABI-mandated alignment for a vector type, if any
|
||||
#[inline]
|
||||
pub fn vector_align(&self, vec_size: Size) -> AbiAndPrefAlign {
|
||||
for &(size, align) in &self.vector_align {
|
||||
if size == vec_size {
|
||||
return align;
|
||||
}
|
||||
}
|
||||
// Default to natural alignment, which is what LLVM does.
|
||||
// That is, use the size, rounded up to a power of 2.
|
||||
AbiAndPrefAlign::new(Align::from_bytes(vec_size.bytes().next_power_of_two()).unwrap())
|
||||
fn cabi_vector_align(&self, vec_size: Size) -> Option<AbiAndPrefAlign> {
|
||||
self.vector_align
|
||||
.iter()
|
||||
.find(|(size, _align)| *size == vec_size)
|
||||
.map(|(_size, align)| *align)
|
||||
}
|
||||
|
||||
/// an alignment resembling the one LLVM would pick for a vector
|
||||
#[inline]
|
||||
pub fn llvmlike_vector_align(&self, vec_size: Size) -> AbiAndPrefAlign {
|
||||
self.cabi_vector_align(vec_size).unwrap_or(AbiAndPrefAlign::new(
|
||||
Align::from_bytes(vec_size.bytes().next_power_of_two()).unwrap(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -810,20 +815,19 @@ impl Align {
|
|||
self.bits().try_into().unwrap()
|
||||
}
|
||||
|
||||
/// Computes the best alignment possible for the given offset
|
||||
/// (the largest power of two that the offset is a multiple of).
|
||||
/// Obtain the greatest factor of `size` that is an alignment
|
||||
/// (the largest power of two the Size is a multiple of).
|
||||
///
|
||||
/// N.B., for an offset of `0`, this happens to return `2^64`.
|
||||
/// Note that all numbers are factors of 0
|
||||
#[inline]
|
||||
pub fn max_for_offset(offset: Size) -> Align {
|
||||
Align { pow2: offset.bytes().trailing_zeros() as u8 }
|
||||
pub fn max_aligned_factor(size: Size) -> Align {
|
||||
Align { pow2: size.bytes().trailing_zeros() as u8 }
|
||||
}
|
||||
|
||||
/// Lower the alignment, if necessary, such that the given offset
|
||||
/// is aligned to it (the offset is a multiple of the alignment).
|
||||
/// Reduces Align to an aligned factor of `size`.
|
||||
#[inline]
|
||||
pub fn restrict_for_offset(self, offset: Size) -> Align {
|
||||
self.min(Align::max_for_offset(offset))
|
||||
pub fn restrict_for_offset(self, size: Size) -> Align {
|
||||
self.min(Align::max_aligned_factor(size))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1455,37 +1459,38 @@ impl BackendRepr {
|
|||
matches!(*self, BackendRepr::Scalar(s) if s.is_bool())
|
||||
}
|
||||
|
||||
/// Returns the fixed alignment of this ABI, if any is mandated.
|
||||
pub fn inherent_align<C: HasDataLayout>(&self, cx: &C) -> Option<AbiAndPrefAlign> {
|
||||
Some(match *self {
|
||||
BackendRepr::Scalar(s) => s.align(cx),
|
||||
BackendRepr::ScalarPair(s1, s2) => s1.align(cx).max(s2.align(cx)),
|
||||
BackendRepr::Vector { element, count } => {
|
||||
cx.data_layout().vector_align(element.size(cx) * count)
|
||||
}
|
||||
BackendRepr::Memory { .. } => return None,
|
||||
})
|
||||
/// The psABI alignment for a `Scalar` or `ScalarPair`
|
||||
///
|
||||
/// `None` for other variants.
|
||||
pub fn scalar_align<C: HasDataLayout>(&self, cx: &C) -> Option<Align> {
|
||||
match *self {
|
||||
BackendRepr::Scalar(s) => Some(s.align(cx).abi),
|
||||
BackendRepr::ScalarPair(s1, s2) => Some(s1.align(cx).max(s2.align(cx)).abi),
|
||||
// The align of a Vector can vary in surprising ways
|
||||
BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the fixed size of this ABI, if any is mandated.
|
||||
pub fn inherent_size<C: HasDataLayout>(&self, cx: &C) -> Option<Size> {
|
||||
Some(match *self {
|
||||
BackendRepr::Scalar(s) => {
|
||||
// No padding in scalars.
|
||||
s.size(cx)
|
||||
}
|
||||
/// The psABI size for a `Scalar` or `ScalarPair`
|
||||
///
|
||||
/// `None` for other variants
|
||||
pub fn scalar_size<C: HasDataLayout>(&self, cx: &C) -> Option<Size> {
|
||||
match *self {
|
||||
// No padding in scalars.
|
||||
BackendRepr::Scalar(s) => Some(s.size(cx)),
|
||||
// May have some padding between the pair.
|
||||
BackendRepr::ScalarPair(s1, s2) => {
|
||||
// May have some padding between the pair.
|
||||
let field2_offset = s1.size(cx).align_to(s2.align(cx).abi);
|
||||
(field2_offset + s2.size(cx)).align_to(self.inherent_align(cx)?.abi)
|
||||
let size = (field2_offset + s2.size(cx)).align_to(
|
||||
self.scalar_align(cx)
|
||||
// We absolutely must have an answer here or everything is FUBAR.
|
||||
.unwrap(),
|
||||
);
|
||||
Some(size)
|
||||
}
|
||||
BackendRepr::Vector { element, count } => {
|
||||
// No padding in vectors, except possibly for trailing padding
|
||||
// to make the size a multiple of align (e.g. for vectors of size 3).
|
||||
(element.size(cx) * count).align_to(self.inherent_align(cx)?.abi)
|
||||
}
|
||||
BackendRepr::Memory { .. } => return None,
|
||||
})
|
||||
// The size of a Vector can vary in surprising ways
|
||||
BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Discard validity range information and allow undef.
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
use std::collections::hash_map::Entry;
|
||||
use std::fmt::Write;
|
||||
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::*;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::{Span, kw, sym};
|
||||
use rustc_span::{Span, sym};
|
||||
use rustc_target::asm;
|
||||
|
||||
use super::LoweringContext;
|
||||
|
|
@ -230,20 +229,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
tokens: None,
|
||||
};
|
||||
|
||||
// Wrap the expression in an AnonConst.
|
||||
let parent_def_id = self.current_hir_id_owner.def_id;
|
||||
let node_id = self.next_node_id();
|
||||
self.create_def(
|
||||
parent_def_id,
|
||||
node_id,
|
||||
kw::Empty,
|
||||
DefKind::AnonConst,
|
||||
*op_sp,
|
||||
);
|
||||
let anon_const = AnonConst { id: node_id, value: P(expr) };
|
||||
hir::InlineAsmOperand::SymFn {
|
||||
anon_const: self.lower_anon_const_to_anon_const(&anon_const),
|
||||
}
|
||||
hir::InlineAsmOperand::SymFn { expr: self.lower_expr(&expr) }
|
||||
}
|
||||
}
|
||||
InlineAsmOperand::Label { block } => {
|
||||
|
|
|
|||
|
|
@ -251,7 +251,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
.arena
|
||||
.alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
|
||||
},
|
||||
ItemKind::GlobalAsm(asm) => hir::ItemKind::GlobalAsm(self.lower_inline_asm(span, asm)),
|
||||
ItemKind::GlobalAsm(asm) => {
|
||||
let asm = self.lower_inline_asm(span, asm);
|
||||
let fake_body =
|
||||
self.lower_body(|this| (&[], this.expr(span, hir::ExprKind::InlineAsm(asm))));
|
||||
hir::ItemKind::GlobalAsm { asm, fake_body }
|
||||
}
|
||||
ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => {
|
||||
// We lower
|
||||
//
|
||||
|
|
|
|||
|
|
@ -126,6 +126,11 @@ pub(crate) enum DefiningTy<'tcx> {
|
|||
/// The MIR represents an inline const. The signature has no inputs and a
|
||||
/// single return value found via `InlineConstArgs::ty`.
|
||||
InlineConst(DefId, GenericArgsRef<'tcx>),
|
||||
|
||||
// Fake body for a global asm. Not particularly useful or interesting,
|
||||
// but we need it so we can properly store the typeck results of the asm
|
||||
// operands, which aren't associated with a body otherwise.
|
||||
GlobalAsm(DefId),
|
||||
}
|
||||
|
||||
impl<'tcx> DefiningTy<'tcx> {
|
||||
|
|
@ -138,9 +143,10 @@ impl<'tcx> DefiningTy<'tcx> {
|
|||
DefiningTy::Closure(_, args) => args.as_closure().upvar_tys(),
|
||||
DefiningTy::CoroutineClosure(_, args) => args.as_coroutine_closure().upvar_tys(),
|
||||
DefiningTy::Coroutine(_, args) => args.as_coroutine().upvar_tys(),
|
||||
DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => {
|
||||
ty::List::empty()
|
||||
}
|
||||
DefiningTy::FnDef(..)
|
||||
| DefiningTy::Const(..)
|
||||
| DefiningTy::InlineConst(..)
|
||||
| DefiningTy::GlobalAsm(_) => ty::List::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -152,7 +158,10 @@ impl<'tcx> DefiningTy<'tcx> {
|
|||
DefiningTy::Closure(..)
|
||||
| DefiningTy::CoroutineClosure(..)
|
||||
| DefiningTy::Coroutine(..) => 1,
|
||||
DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => 0,
|
||||
DefiningTy::FnDef(..)
|
||||
| DefiningTy::Const(..)
|
||||
| DefiningTy::InlineConst(..)
|
||||
| DefiningTy::GlobalAsm(_) => 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -171,7 +180,8 @@ impl<'tcx> DefiningTy<'tcx> {
|
|||
| DefiningTy::Coroutine(def_id, ..)
|
||||
| DefiningTy::FnDef(def_id, ..)
|
||||
| DefiningTy::Const(def_id, ..)
|
||||
| DefiningTy::InlineConst(def_id, ..) => def_id,
|
||||
| DefiningTy::InlineConst(def_id, ..)
|
||||
| DefiningTy::GlobalAsm(def_id) => def_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -411,6 +421,7 @@ impl<'tcx> UniversalRegions<'tcx> {
|
|||
tcx.def_path_str_with_args(def_id, args),
|
||||
));
|
||||
}
|
||||
DefiningTy::GlobalAsm(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -633,6 +644,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
|||
DefiningTy::InlineConst(self.mir_def.to_def_id(), args)
|
||||
}
|
||||
}
|
||||
|
||||
BodyOwnerKind::GlobalAsm => DefiningTy::GlobalAsm(self.mir_def.to_def_id()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -666,6 +679,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
|||
}
|
||||
|
||||
DefiningTy::FnDef(_, args) | DefiningTy::Const(_, args) => args,
|
||||
|
||||
DefiningTy::GlobalAsm(_) => ty::List::empty(),
|
||||
};
|
||||
|
||||
let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static));
|
||||
|
|
@ -802,6 +817,10 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
|||
let ty = args.as_inline_const().ty();
|
||||
ty::Binder::dummy(tcx.mk_type_list(&[ty]))
|
||||
}
|
||||
|
||||
DefiningTy::GlobalAsm(def_id) => {
|
||||
ty::Binder::dummy(tcx.mk_type_list(&[tcx.type_of(def_id).instantiate_identity()]))
|
||||
}
|
||||
};
|
||||
|
||||
// FIXME(#129952): We probably want a more principled approach here.
|
||||
|
|
|
|||
|
|
@ -19,16 +19,12 @@ pub fn inject(
|
|||
let edition = sess.psess.edition;
|
||||
|
||||
// the first name in this list is the crate name of the crate with the prelude
|
||||
let names: &[Symbol] = if attr::contains_name(pre_configured_attrs, sym::no_core) {
|
||||
let name: Symbol = if attr::contains_name(pre_configured_attrs, sym::no_core) {
|
||||
return 0;
|
||||
} else if attr::contains_name(pre_configured_attrs, sym::no_std) {
|
||||
if attr::contains_name(pre_configured_attrs, sym::compiler_builtins) {
|
||||
&[sym::core]
|
||||
} else {
|
||||
&[sym::core, sym::compiler_builtins]
|
||||
}
|
||||
sym::core
|
||||
} else {
|
||||
&[sym::std]
|
||||
sym::std
|
||||
};
|
||||
|
||||
let expn_id = resolver.expansion_for_ast_pass(
|
||||
|
|
@ -43,36 +39,16 @@ pub fn inject(
|
|||
let ecfg = ExpansionConfig::default("std_lib_injection".to_string(), features);
|
||||
let cx = ExtCtxt::new(sess, ecfg, resolver, None);
|
||||
|
||||
// .rev() to preserve ordering above in combination with insert(0, ...)
|
||||
for &name in names.iter().rev() {
|
||||
let ident_span = if edition >= Edition2018 { span } else { call_site };
|
||||
let item = if name == sym::compiler_builtins {
|
||||
// compiler_builtins is a private implementation detail. We only
|
||||
// need to insert it into the crate graph for linking and should not
|
||||
// expose any of its public API.
|
||||
//
|
||||
// FIXME(#113634) We should inject this during post-processing like
|
||||
// we do for the panic runtime, profiler runtime, etc.
|
||||
cx.item(
|
||||
span,
|
||||
Ident::new(kw::Underscore, ident_span),
|
||||
thin_vec![],
|
||||
ast::ItemKind::ExternCrate(Some(name)),
|
||||
)
|
||||
} else {
|
||||
cx.item(
|
||||
span,
|
||||
Ident::new(name, ident_span),
|
||||
thin_vec![cx.attr_word(sym::macro_use, span)],
|
||||
ast::ItemKind::ExternCrate(None),
|
||||
)
|
||||
};
|
||||
krate.items.insert(0, item);
|
||||
}
|
||||
let ident_span = if edition >= Edition2018 { span } else { call_site };
|
||||
|
||||
// The crates have been injected, the assumption is that the first one is
|
||||
// the one with the prelude.
|
||||
let name = names[0];
|
||||
let item = cx.item(
|
||||
span,
|
||||
Ident::new(name, ident_span),
|
||||
thin_vec![cx.attr_word(sym::macro_use, span)],
|
||||
ast::ItemKind::ExternCrate(None),
|
||||
);
|
||||
|
||||
krate.items.insert(0, item);
|
||||
|
||||
let root = (edition == Edition2015).then_some(kw::PathRoot);
|
||||
|
||||
|
|
@ -88,6 +64,7 @@ pub fn inject(
|
|||
.map(|&symbol| Ident::new(symbol, span))
|
||||
.collect();
|
||||
|
||||
// Inject the relevant crate's prelude.
|
||||
let use_item = cx.item(
|
||||
span,
|
||||
Ident::empty(),
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ index 7165c3e48af..968552ad435 100644
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
core = { path = "../core" }
|
||||
core = { path = "../core", public = true }
|
||||
-compiler_builtins = { version = "=0.1.146", features = ['rustc-dep-of-std'] }
|
||||
+compiler_builtins = { version = "=0.1.146", features = ['rustc-dep-of-std', 'no-f16-f128'] }
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use crate::prelude::*;
|
|||
|
||||
pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) {
|
||||
let item = tcx.hir_item(item_id);
|
||||
if let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind {
|
||||
if let rustc_hir::ItemKind::GlobalAsm { asm, .. } = item.kind {
|
||||
let is_x86 =
|
||||
matches!(tcx.sess.asm_arch.unwrap(), InlineAsmArch::X86 | InlineAsmArch::X86_64);
|
||||
|
||||
|
|
@ -55,7 +55,7 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
|
|||
}
|
||||
}
|
||||
}
|
||||
InlineAsmOperand::SymFn { anon_const } => {
|
||||
InlineAsmOperand::SymFn { expr } => {
|
||||
if cfg!(not(feature = "inline_asm_sym")) {
|
||||
tcx.dcx().span_err(
|
||||
item.span,
|
||||
|
|
@ -63,7 +63,7 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
|
|||
);
|
||||
}
|
||||
|
||||
let ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
|
||||
let ty = tcx.typeck(item_id.owner_id).expr_ty(expr);
|
||||
let instance = match ty.kind() {
|
||||
&ty::FnDef(def_id, args) => Instance::new(def_id, args),
|
||||
_ => span_bug!(op_sp, "asm sym is not a function"),
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
|
|||
}
|
||||
MonoItem::GlobalAsm(item_id) => {
|
||||
let item = cx.tcx().hir_item(item_id);
|
||||
if let hir::ItemKind::GlobalAsm(asm) = item.kind {
|
||||
if let hir::ItemKind::GlobalAsm { asm, .. } = item.kind {
|
||||
let operands: Vec<_> = asm
|
||||
.operands
|
||||
.iter()
|
||||
|
|
@ -71,11 +71,8 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
hir::InlineAsmOperand::SymFn { ref anon_const } => {
|
||||
let ty = cx
|
||||
.tcx()
|
||||
.typeck_body(anon_const.body)
|
||||
.node_type(anon_const.hir_id);
|
||||
hir::InlineAsmOperand::SymFn { expr } => {
|
||||
let ty = cx.tcx().typeck(item_id.owner_id).expr_ty(expr);
|
||||
let instance = match ty.kind() {
|
||||
&ty::FnDef(def_id, args) => Instance::new(def_id, args),
|
||||
_ => span_bug!(*op_sp, "asm sym is not a function"),
|
||||
|
|
|
|||
|
|
@ -1913,13 +1913,18 @@ pub enum BodyOwnerKind {
|
|||
|
||||
/// Initializer of a `static` item.
|
||||
Static(Mutability),
|
||||
|
||||
/// Fake body for a global asm to store its const-like value types.
|
||||
GlobalAsm,
|
||||
}
|
||||
|
||||
impl BodyOwnerKind {
|
||||
pub fn is_fn_or_closure(self) -> bool {
|
||||
match self {
|
||||
BodyOwnerKind::Fn | BodyOwnerKind::Closure => true,
|
||||
BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(_) => false,
|
||||
BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(_) | BodyOwnerKind::GlobalAsm => {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3420,7 +3425,7 @@ pub enum InlineAsmOperand<'hir> {
|
|||
anon_const: &'hir AnonConst,
|
||||
},
|
||||
SymFn {
|
||||
anon_const: &'hir AnonConst,
|
||||
expr: &'hir Expr<'hir>,
|
||||
},
|
||||
SymStatic {
|
||||
path: QPath<'hir>,
|
||||
|
|
@ -3848,7 +3853,7 @@ impl<'hir> Item<'hir> {
|
|||
expect_foreign_mod, (ExternAbi, &'hir [ForeignItemRef]),
|
||||
ItemKind::ForeignMod { abi, items }, (*abi, items);
|
||||
|
||||
expect_global_asm, &'hir InlineAsm<'hir>, ItemKind::GlobalAsm(asm), asm;
|
||||
expect_global_asm, &'hir InlineAsm<'hir>, ItemKind::GlobalAsm { asm, .. }, asm;
|
||||
|
||||
expect_ty_alias, (&'hir Ty<'hir>, &'hir Generics<'hir>),
|
||||
ItemKind::TyAlias(ty, generics), (ty, generics);
|
||||
|
|
@ -4015,7 +4020,15 @@ pub enum ItemKind<'hir> {
|
|||
/// An external module, e.g. `extern { .. }`.
|
||||
ForeignMod { abi: ExternAbi, items: &'hir [ForeignItemRef] },
|
||||
/// Module-level inline assembly (from `global_asm!`).
|
||||
GlobalAsm(&'hir InlineAsm<'hir>),
|
||||
GlobalAsm {
|
||||
asm: &'hir InlineAsm<'hir>,
|
||||
/// A fake body which stores typeck results for the global asm's sym_fn
|
||||
/// operands, which are represented as path expressions. This body contains
|
||||
/// a single [`ExprKind::InlineAsm`] which points to the asm in the field
|
||||
/// above, and which is typechecked like a inline asm expr just for the
|
||||
/// typeck results.
|
||||
fake_body: BodyId,
|
||||
},
|
||||
/// A type alias, e.g., `type Foo = Bar<u8>`.
|
||||
TyAlias(&'hir Ty<'hir>, &'hir Generics<'hir>),
|
||||
/// An enum definition, e.g., `enum Foo<A, B> {C<A>, D<B>}`.
|
||||
|
|
@ -4081,7 +4094,7 @@ impl ItemKind<'_> {
|
|||
ItemKind::Macro(..) => "macro",
|
||||
ItemKind::Mod(..) => "module",
|
||||
ItemKind::ForeignMod { .. } => "extern block",
|
||||
ItemKind::GlobalAsm(..) => "global asm item",
|
||||
ItemKind::GlobalAsm { .. } => "global asm item",
|
||||
ItemKind::TyAlias(..) => "type alias",
|
||||
ItemKind::Enum(..) => "enum",
|
||||
ItemKind::Struct(..) => "struct",
|
||||
|
|
@ -4540,6 +4553,10 @@ impl<'hir> Node<'hir> {
|
|||
..
|
||||
}) => Some((owner_id.def_id, *body)),
|
||||
|
||||
Node::Item(Item {
|
||||
owner_id, kind: ItemKind::GlobalAsm { asm: _, fake_body }, ..
|
||||
}) => Some((owner_id.def_id, *fake_body)),
|
||||
|
||||
Node::Expr(Expr { kind: ExprKind::Closure(Closure { def_id, body, .. }), .. }) => {
|
||||
Some((*def_id, *body))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -573,9 +573,13 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
|
|||
try_visit!(visitor.visit_id(item.hir_id()));
|
||||
walk_list!(visitor, visit_foreign_item_ref, items);
|
||||
}
|
||||
ItemKind::GlobalAsm(asm) => {
|
||||
ItemKind::GlobalAsm { asm: _, fake_body } => {
|
||||
try_visit!(visitor.visit_id(item.hir_id()));
|
||||
try_visit!(visitor.visit_inline_asm(asm, item.hir_id()));
|
||||
// Visit the fake body, which contains the asm statement.
|
||||
// Therefore we should not visit the asm statement again
|
||||
// outside of the body, or some visitors won't have their
|
||||
// typeck results set correctly.
|
||||
try_visit!(visitor.visit_nested_body(fake_body));
|
||||
}
|
||||
ItemKind::TyAlias(ref ty, ref generics) => {
|
||||
try_visit!(visitor.visit_id(item.hir_id()));
|
||||
|
|
@ -1442,10 +1446,12 @@ pub fn walk_inline_asm<'v, V: Visitor<'v>>(
|
|||
try_visit!(visitor.visit_expr(in_expr));
|
||||
visit_opt!(visitor, visit_expr, out_expr);
|
||||
}
|
||||
InlineAsmOperand::Const { anon_const, .. }
|
||||
| InlineAsmOperand::SymFn { anon_const, .. } => {
|
||||
InlineAsmOperand::Const { anon_const, .. } => {
|
||||
try_visit!(visitor.visit_anon_const(anon_const));
|
||||
}
|
||||
InlineAsmOperand::SymFn { expr, .. } => {
|
||||
try_visit!(visitor.visit_expr(expr));
|
||||
}
|
||||
InlineAsmOperand::SymStatic { path, .. } => {
|
||||
try_visit!(visitor.visit_qpath(path, id, *op_sp));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ impl Target {
|
|||
ItemKind::Macro(..) => Target::MacroDef,
|
||||
ItemKind::Mod(..) => Target::Mod,
|
||||
ItemKind::ForeignMod { .. } => Target::ForeignMod,
|
||||
ItemKind::GlobalAsm(..) => Target::GlobalAsm,
|
||||
ItemKind::GlobalAsm { .. } => Target::GlobalAsm,
|
||||
ItemKind::TyAlias(..) => Target::TyAlias,
|
||||
ItemKind::Enum(..) => Target::Enum,
|
||||
ItemKind::Struct(..) => Target::Struct,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ use rustc_lint_defs::builtin::{
|
|||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
|
||||
use rustc_middle::middle::stability::EvalResult;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::error::TypeErrorToStringExt;
|
||||
use rustc_middle::ty::fold::{BottomUpFolder, fold_regions};
|
||||
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
|
||||
|
|
@ -35,7 +34,6 @@ use {rustc_attr_parsing as attr, rustc_hir as hir};
|
|||
|
||||
use super::compare_impl_item::check_type_bounds;
|
||||
use super::*;
|
||||
use crate::check::intrinsicck::InlineAsmCtxt;
|
||||
|
||||
pub fn check_abi(tcx: TyCtxt<'_>, span: Span, abi: ExternAbi) {
|
||||
if !tcx.sess.target.is_abi_supported(abi) {
|
||||
|
|
@ -895,13 +893,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
}
|
||||
}
|
||||
}
|
||||
DefKind::GlobalAsm => {
|
||||
let it = tcx.hir().expect_item(def_id);
|
||||
let hir::ItemKind::GlobalAsm(asm) = it.kind else {
|
||||
span_bug!(it.span, "DefKind::GlobalAsm but got {:#?}", it)
|
||||
};
|
||||
InlineAsmCtxt::new_global_asm(tcx).check_asm(asm, def_id);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxIndexSet;
|
|||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{self as hir, LangItem};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy};
|
||||
use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy};
|
||||
use rustc_session::lint;
|
||||
use rustc_span::def_id::LocalDefId;
|
||||
use rustc_span::{Symbol, sym};
|
||||
|
|
@ -16,10 +16,11 @@ use rustc_target::asm::{
|
|||
|
||||
use crate::errors::RegisterTypeUnstable;
|
||||
|
||||
pub struct InlineAsmCtxt<'a, 'tcx> {
|
||||
pub struct InlineAsmCtxt<'a, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
typing_env: ty::TypingEnv<'tcx>,
|
||||
get_operand_ty: Box<dyn Fn(&'tcx hir::Expr<'tcx>) -> Ty<'tcx> + 'a>,
|
||||
target_features: &'tcx FxIndexSet<Symbol>,
|
||||
expr_ty: Box<dyn Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a>,
|
||||
}
|
||||
|
||||
enum NonAsmTypeReason<'tcx> {
|
||||
|
|
@ -29,25 +30,24 @@ enum NonAsmTypeReason<'tcx> {
|
|||
}
|
||||
|
||||
impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
||||
pub fn new_global_asm(tcx: TyCtxt<'tcx>) -> Self {
|
||||
pub fn new(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: LocalDefId,
|
||||
get_operand_ty: impl Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a,
|
||||
) -> Self {
|
||||
InlineAsmCtxt {
|
||||
tcx,
|
||||
typing_env: ty::TypingEnv {
|
||||
typing_mode: ty::TypingMode::non_body_analysis(),
|
||||
param_env: ty::ParamEnv::empty(),
|
||||
},
|
||||
get_operand_ty: Box::new(|e| bug!("asm operand in global asm: {e:?}")),
|
||||
target_features: tcx.asm_target_features(def_id),
|
||||
expr_ty: Box::new(get_operand_ty),
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(#132279): This likely causes us to incorrectly handle opaque types in their
|
||||
// defining scope.
|
||||
pub fn new_in_fn(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
typing_env: ty::TypingEnv<'tcx>,
|
||||
get_operand_ty: impl Fn(&'tcx hir::Expr<'tcx>) -> Ty<'tcx> + 'a,
|
||||
) -> Self {
|
||||
InlineAsmCtxt { tcx, typing_env, get_operand_ty: Box::new(get_operand_ty) }
|
||||
fn expr_ty(&self, expr: &hir::Expr<'tcx>) -> Ty<'tcx> {
|
||||
(self.expr_ty)(expr)
|
||||
}
|
||||
|
||||
// FIXME(compiler-errors): This could use `<$ty as Pointee>::Metadata == ()`
|
||||
|
|
@ -139,9 +139,8 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
template: &[InlineAsmTemplatePiece],
|
||||
is_input: bool,
|
||||
tied_input: Option<(&'tcx hir::Expr<'tcx>, Option<InlineAsmType>)>,
|
||||
target_features: &FxIndexSet<Symbol>,
|
||||
) -> Option<InlineAsmType> {
|
||||
let ty = (self.get_operand_ty)(expr);
|
||||
let ty = self.expr_ty(expr);
|
||||
if ty.has_non_region_infer() {
|
||||
bug!("inference variable in asm operand ty: {:?} {:?}", expr, ty);
|
||||
}
|
||||
|
|
@ -229,7 +228,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
if let Some((in_expr, Some(in_asm_ty))) = tied_input {
|
||||
if in_asm_ty != asm_ty {
|
||||
let msg = "incompatible types for asm inout argument";
|
||||
let in_expr_ty = (self.get_operand_ty)(in_expr);
|
||||
let in_expr_ty = self.expr_ty(in_expr);
|
||||
self.tcx
|
||||
.dcx()
|
||||
.struct_span_err(vec![in_expr.span, expr.span], msg)
|
||||
|
|
@ -291,7 +290,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
// (!). In that case we still need the earlier check to verify that the
|
||||
// register class is usable at all.
|
||||
if let Some(feature) = feature {
|
||||
if !target_features.contains(feature) {
|
||||
if !self.target_features.contains(feature) {
|
||||
let msg = format!("`{feature}` target feature is not enabled");
|
||||
self.tcx
|
||||
.dcx()
|
||||
|
|
@ -351,14 +350,13 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
Some(asm_ty)
|
||||
}
|
||||
|
||||
pub fn check_asm(&self, asm: &hir::InlineAsm<'tcx>, enclosing_id: LocalDefId) {
|
||||
let target_features = self.tcx.asm_target_features(enclosing_id.to_def_id());
|
||||
pub fn check_asm(&self, asm: &hir::InlineAsm<'tcx>) {
|
||||
let Some(asm_arch) = self.tcx.sess.asm_arch else {
|
||||
self.tcx.dcx().delayed_bug("target architecture does not support asm");
|
||||
return;
|
||||
};
|
||||
let allow_experimental_reg = self.tcx.features().asm_experimental_reg();
|
||||
for (idx, (op, op_sp)) in asm.operands.iter().enumerate() {
|
||||
for (idx, &(op, op_sp)) in asm.operands.iter().enumerate() {
|
||||
// Validate register classes against currently enabled target
|
||||
// features. We check that at least one type is available for
|
||||
// the enabled features.
|
||||
|
|
@ -381,12 +379,12 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
if let Err(msg) = reg.validate(
|
||||
asm_arch,
|
||||
self.tcx.sess.relocation_model(),
|
||||
target_features,
|
||||
self.target_features,
|
||||
&self.tcx.sess.target,
|
||||
op.is_clobber(),
|
||||
) {
|
||||
let msg = format!("cannot use register `{}`: {}", reg.name(), msg);
|
||||
self.tcx.dcx().span_err(*op_sp, msg);
|
||||
self.tcx.dcx().span_err(op_sp, msg);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
@ -401,7 +399,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
{
|
||||
match feature {
|
||||
Some(feature) => {
|
||||
if target_features.contains(&feature) {
|
||||
if self.target_features.contains(&feature) {
|
||||
missing_required_features.clear();
|
||||
break;
|
||||
} else {
|
||||
|
|
@ -426,7 +424,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
reg_class.name(),
|
||||
feature
|
||||
);
|
||||
self.tcx.dcx().span_err(*op_sp, msg);
|
||||
self.tcx.dcx().span_err(op_sp, msg);
|
||||
// register isn't enabled, don't do more checks
|
||||
continue;
|
||||
}
|
||||
|
|
@ -440,7 +438,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
.intersperse(", ")
|
||||
.collect::<String>(),
|
||||
);
|
||||
self.tcx.dcx().span_err(*op_sp, msg);
|
||||
self.tcx.dcx().span_err(op_sp, msg);
|
||||
// register isn't enabled, don't do more checks
|
||||
continue;
|
||||
}
|
||||
|
|
@ -448,52 +446,21 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
match *op {
|
||||
match op {
|
||||
hir::InlineAsmOperand::In { reg, expr } => {
|
||||
self.check_asm_operand_type(
|
||||
idx,
|
||||
reg,
|
||||
expr,
|
||||
asm.template,
|
||||
true,
|
||||
None,
|
||||
target_features,
|
||||
);
|
||||
self.check_asm_operand_type(idx, reg, expr, asm.template, true, None);
|
||||
}
|
||||
hir::InlineAsmOperand::Out { reg, late: _, expr } => {
|
||||
if let Some(expr) = expr {
|
||||
self.check_asm_operand_type(
|
||||
idx,
|
||||
reg,
|
||||
expr,
|
||||
asm.template,
|
||||
false,
|
||||
None,
|
||||
target_features,
|
||||
);
|
||||
self.check_asm_operand_type(idx, reg, expr, asm.template, false, None);
|
||||
}
|
||||
}
|
||||
hir::InlineAsmOperand::InOut { reg, late: _, expr } => {
|
||||
self.check_asm_operand_type(
|
||||
idx,
|
||||
reg,
|
||||
expr,
|
||||
asm.template,
|
||||
false,
|
||||
None,
|
||||
target_features,
|
||||
);
|
||||
self.check_asm_operand_type(idx, reg, expr, asm.template, false, None);
|
||||
}
|
||||
hir::InlineAsmOperand::SplitInOut { reg, late: _, in_expr, out_expr } => {
|
||||
let in_ty = self.check_asm_operand_type(
|
||||
idx,
|
||||
reg,
|
||||
in_expr,
|
||||
asm.template,
|
||||
true,
|
||||
None,
|
||||
target_features,
|
||||
);
|
||||
let in_ty =
|
||||
self.check_asm_operand_type(idx, reg, in_expr, asm.template, true, None);
|
||||
if let Some(out_expr) = out_expr {
|
||||
self.check_asm_operand_type(
|
||||
idx,
|
||||
|
|
@ -502,7 +469,6 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
asm.template,
|
||||
false,
|
||||
Some((in_expr, in_ty)),
|
||||
target_features,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -514,11 +480,25 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
|
|||
);
|
||||
}
|
||||
// Typeck has checked that SymFn refers to a function.
|
||||
hir::InlineAsmOperand::SymFn { anon_const } => {
|
||||
debug_assert_matches!(
|
||||
self.tcx.type_of(anon_const.def_id).instantiate_identity().kind(),
|
||||
ty::Error(_) | ty::FnDef(..)
|
||||
);
|
||||
hir::InlineAsmOperand::SymFn { expr } => {
|
||||
let ty = self.expr_ty(expr);
|
||||
match ty.kind() {
|
||||
ty::FnDef(..) => {}
|
||||
ty::Error(_) => {}
|
||||
_ => {
|
||||
self.tcx
|
||||
.dcx()
|
||||
.struct_span_err(op_sp, "invalid `sym` operand")
|
||||
.with_span_label(
|
||||
expr.span,
|
||||
format!("is {} `{}`", ty.kind().article(), ty),
|
||||
)
|
||||
.with_help(
|
||||
"`sym` operands must refer to either a function or a static",
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
// AST lowering guarantees that SymStatic points to a static.
|
||||
hir::InlineAsmOperand::SymStatic { .. } => {}
|
||||
|
|
|
|||
|
|
@ -680,7 +680,7 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
|
|||
| hir::ItemKind::Use(..)
|
||||
| hir::ItemKind::Macro(..)
|
||||
| hir::ItemKind::Mod(_)
|
||||
| hir::ItemKind::GlobalAsm(_) => {}
|
||||
| hir::ItemKind::GlobalAsm { .. } => {}
|
||||
hir::ItemKind::ForeignMod { items, .. } => {
|
||||
for item in *items {
|
||||
let item = tcx.hir_foreign_item(item.id);
|
||||
|
|
|
|||
|
|
@ -189,8 +189,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
|||
// Exclude `GlobalAsm` here which cannot have generics.
|
||||
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
|
||||
if asm.operands.iter().any(|(op, _op_sp)| match op {
|
||||
hir::InlineAsmOperand::Const { anon_const }
|
||||
| hir::InlineAsmOperand::SymFn { anon_const } => {
|
||||
hir::InlineAsmOperand::Const { anon_const } => {
|
||||
anon_const.hir_id == hir_id
|
||||
}
|
||||
_ => false,
|
||||
|
|
|
|||
|
|
@ -623,7 +623,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
|||
| hir::ItemKind::Mod(..)
|
||||
| hir::ItemKind::ForeignMod { .. }
|
||||
| hir::ItemKind::Static(..)
|
||||
| hir::ItemKind::GlobalAsm(..) => {
|
||||
| hir::ItemKind::GlobalAsm { .. } => {
|
||||
// These sorts of items have no lifetime parameters at all.
|
||||
intravisit::walk_item(self, item);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,13 +35,6 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx
|
|||
let parent_node_id = tcx.parent_hir_id(hir_id);
|
||||
let parent_node = tcx.hir_node(parent_node_id);
|
||||
|
||||
let find_sym_fn = |&(op, op_sp)| match op {
|
||||
hir::InlineAsmOperand::SymFn { anon_const } if anon_const.hir_id == hir_id => {
|
||||
Some((anon_const, op_sp))
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let find_const = |&(op, op_sp)| match op {
|
||||
hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == hir_id => {
|
||||
Some((anon_const, op_sp))
|
||||
|
|
@ -59,31 +52,7 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx
|
|||
|
||||
// Anon consts outside the type system.
|
||||
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
|
||||
| Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
|
||||
if let Some((anon_const, op_sp)) = asm.operands.iter().find_map(find_sym_fn) =>
|
||||
{
|
||||
let ty = tcx.typeck(def_id).node_type(hir_id);
|
||||
|
||||
match ty.kind() {
|
||||
ty::Error(_) => ty,
|
||||
ty::FnDef(..) => ty,
|
||||
_ => {
|
||||
let guar = tcx
|
||||
.dcx()
|
||||
.struct_span_err(op_sp, "invalid `sym` operand")
|
||||
.with_span_label(
|
||||
tcx.def_span(anon_const.def_id),
|
||||
format!("is {} `{}`", ty.kind().article(), ty),
|
||||
)
|
||||
.with_help("`sym` operands must refer to either a function or a static")
|
||||
.emit();
|
||||
|
||||
Ty::new_error(tcx, guar)
|
||||
}
|
||||
}
|
||||
}
|
||||
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
|
||||
| Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
|
||||
| Node::Item(&Item { kind: ItemKind::GlobalAsm { asm, .. }, .. })
|
||||
if let Some((anon_const, op_sp)) = asm.operands.iter().find_map(find_const) =>
|
||||
{
|
||||
let ty = tcx.typeck(def_id).node_type(hir_id);
|
||||
|
|
@ -313,12 +282,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
|
|||
let args = ty::GenericArgs::identity_for_item(tcx, def_id);
|
||||
Ty::new_adt(tcx, def, args)
|
||||
}
|
||||
ItemKind::GlobalAsm { .. } => tcx.typeck(def_id).node_type(hir_id),
|
||||
ItemKind::Trait(..)
|
||||
| ItemKind::TraitAlias(..)
|
||||
| ItemKind::Macro(..)
|
||||
| ItemKind::Mod(..)
|
||||
| ItemKind::ForeignMod { .. }
|
||||
| ItemKind::GlobalAsm(..)
|
||||
| ItemKind::ExternCrate(..)
|
||||
| ItemKind::Use(..) => {
|
||||
span_bug!(item.span, "compute_type_of_item: unexpected item type: {:?}", item.kind);
|
||||
|
|
|
|||
|
|
@ -692,7 +692,7 @@ impl<'a> State<'a> {
|
|||
}
|
||||
self.bclose(item.span);
|
||||
}
|
||||
hir::ItemKind::GlobalAsm(asm) => {
|
||||
hir::ItemKind::GlobalAsm { asm, .. } => {
|
||||
self.head("global_asm!");
|
||||
self.print_inline_asm(asm);
|
||||
self.end()
|
||||
|
|
@ -1431,10 +1431,10 @@ impl<'a> State<'a> {
|
|||
s.space();
|
||||
s.print_anon_const(anon_const);
|
||||
}
|
||||
hir::InlineAsmOperand::SymFn { ref anon_const } => {
|
||||
hir::InlineAsmOperand::SymFn { ref expr } => {
|
||||
s.word("sym_fn");
|
||||
s.space();
|
||||
s.print_anon_const(anon_const);
|
||||
s.print_expr(expr);
|
||||
}
|
||||
hir::InlineAsmOperand::SymStatic { ref path, def_id: _ } => {
|
||||
s.word("sym_static");
|
||||
|
|
|
|||
|
|
@ -3763,7 +3763,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let mut diverge = asm.asm_macro.diverges(asm.options);
|
||||
|
||||
for (op, _op_sp) in asm.operands {
|
||||
match op {
|
||||
match *op {
|
||||
hir::InlineAsmOperand::In { expr, .. } => {
|
||||
self.check_expr_asm_operand(expr, true);
|
||||
}
|
||||
|
|
@ -3778,10 +3778,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.check_expr_asm_operand(out_expr, false);
|
||||
}
|
||||
}
|
||||
hir::InlineAsmOperand::SymFn { expr } => {
|
||||
self.check_expr(expr);
|
||||
}
|
||||
// `AnonConst`s have their own body and is type-checked separately.
|
||||
// As they don't flow into the type system we don't need them to
|
||||
// be well-formed.
|
||||
hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } => {}
|
||||
hir::InlineAsmOperand::Const { .. } => {}
|
||||
hir::InlineAsmOperand::SymStatic { .. } => {}
|
||||
hir::InlineAsmOperand::Label { block } => {
|
||||
let previous_diverges = self.diverges.get();
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len());
|
||||
for (asm, hir_id) in deferred_asm_checks.drain(..) {
|
||||
let enclosing_id = self.tcx.hir_enclosing_body_owner(hir_id);
|
||||
let get_operand_ty = |expr| {
|
||||
let expr_ty = |expr: &hir::Expr<'tcx>| {
|
||||
let ty = self.typeck_results.borrow().expr_ty_adjusted(expr);
|
||||
let ty = self.resolve_vars_if_possible(ty);
|
||||
if ty.has_non_region_infer() {
|
||||
|
|
@ -110,12 +110,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.tcx.erase_regions(ty)
|
||||
}
|
||||
};
|
||||
InlineAsmCtxt::new_in_fn(
|
||||
self.tcx,
|
||||
self.infcx.typing_env(self.param_env),
|
||||
get_operand_ty,
|
||||
)
|
||||
.check_asm(asm, enclosing_id);
|
||||
InlineAsmCtxt::new(self.tcx, enclosing_id, expr_ty).check_asm(asm);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -133,7 +133,12 @@ fn typeck_with_inspect<'tcx>(
|
|||
}
|
||||
let mut fcx = FnCtxt::new(&root_ctxt, param_env, def_id);
|
||||
|
||||
if let Some(hir::FnSig { header, decl, .. }) = node.fn_sig() {
|
||||
if let hir::Node::Item(hir::Item { kind: hir::ItemKind::GlobalAsm { .. }, .. }) = node {
|
||||
// Check the fake body of a global ASM. There's not much to do here except
|
||||
// for visit the asm expr of the body.
|
||||
let ty = fcx.check_expr(body.value);
|
||||
fcx.write_ty(id, ty);
|
||||
} else if let Some(hir::FnSig { header, decl, .. }) = node.fn_sig() {
|
||||
let fn_sig = if decl.output.is_suggestable_infer_ty().is_some() {
|
||||
// In the case that we're recovering `fn() -> W<_>` or some other return
|
||||
// type that has an infer in it, lower the type directly so that it'll
|
||||
|
|
@ -277,12 +282,9 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti
|
|||
Some(fcx.next_ty_var(span))
|
||||
}
|
||||
Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), span, .. })
|
||||
| Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), span, .. }) => {
|
||||
| Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm { asm, .. }, span, .. }) => {
|
||||
asm.operands.iter().find_map(|(op, _op_sp)| match op {
|
||||
hir::InlineAsmOperand::Const { anon_const }
|
||||
| hir::InlineAsmOperand::SymFn { anon_const }
|
||||
if anon_const.hir_id == id =>
|
||||
{
|
||||
hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == id => {
|
||||
Some(fcx.next_ty_var(span))
|
||||
}
|
||||
_ => None,
|
||||
|
|
|
|||
|
|
@ -905,11 +905,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
} else if self.impl_into_iterator_should_be_iterator(rcvr_ty, span, unsatisfied_predicates)
|
||||
{
|
||||
err.span_label(span, format!("`{rcvr_ty}` is not an iterator"));
|
||||
err.multipart_suggestion_verbose(
|
||||
"call `.into_iter()` first",
|
||||
vec![(span.shrink_to_lo(), format!("into_iter()."))],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
if !span.in_external_macro(self.tcx.sess.source_map()) {
|
||||
err.multipart_suggestion_verbose(
|
||||
"call `.into_iter()` first",
|
||||
vec![(span.shrink_to_lo(), format!("into_iter()."))],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
return err.emit();
|
||||
} else if !unsatisfied_predicates.is_empty() && matches!(rcvr_ty.kind(), ty::Param(_)) {
|
||||
// We special case the situation where we are looking for `_` in
|
||||
|
|
|
|||
|
|
@ -48,13 +48,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
for param in body.params {
|
||||
wbcx.visit_node_id(param.pat.span, param.hir_id);
|
||||
}
|
||||
// Type only exists for constants and statics, not functions.
|
||||
match self.tcx.hir_body_owner_kind(item_def_id) {
|
||||
hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_) => {
|
||||
// Visit the type of a const or static, which is used during THIR building.
|
||||
hir::BodyOwnerKind::Const { .. }
|
||||
| hir::BodyOwnerKind::Static(_)
|
||||
| hir::BodyOwnerKind::GlobalAsm => {
|
||||
let item_hir_id = self.tcx.local_def_id_to_hir_id(item_def_id);
|
||||
wbcx.visit_node_id(body.value.span, item_hir_id);
|
||||
}
|
||||
hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => (),
|
||||
// For closures and consts, we already plan to visit liberated signatures.
|
||||
hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => {}
|
||||
}
|
||||
wbcx.visit_body(body);
|
||||
wbcx.visit_min_capture_map();
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
|
|||
HirItem::ForeignMod { .. } => ("ItemForeignMod", LABELS_HIR_ONLY),
|
||||
|
||||
// Module-level inline assembly (from global_asm!)
|
||||
HirItem::GlobalAsm(..) => ("ItemGlobalAsm", LABELS_HIR_ONLY),
|
||||
HirItem::GlobalAsm { .. } => ("ItemGlobalAsm", LABELS_HIR_ONLY),
|
||||
|
||||
// A type alias, e.g., `type Foo = Bar<u8>`
|
||||
HirItem::TyAlias(..) => ("ItemTy", LABELS_HIR_ONLY),
|
||||
|
|
|
|||
|
|
@ -2907,7 +2907,13 @@ enum AsmLabelKind {
|
|||
impl<'tcx> LateLintPass<'tcx> for AsmLabels {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
|
||||
if let hir::Expr {
|
||||
kind: hir::ExprKind::InlineAsm(hir::InlineAsm { template_strs, options, .. }),
|
||||
kind:
|
||||
hir::ExprKind::InlineAsm(hir::InlineAsm {
|
||||
asm_macro: AsmMacro::Asm | AsmMacro::NakedAsm,
|
||||
template_strs,
|
||||
options,
|
||||
..
|
||||
}),
|
||||
..
|
||||
} = expr
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1740,7 +1740,7 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDefinitions {
|
|||
hir::ItemKind::Impl(..)
|
||||
| hir::ItemKind::TraitAlias(..)
|
||||
| hir::ItemKind::Trait(..)
|
||||
| hir::ItemKind::GlobalAsm(..)
|
||||
| hir::ItemKind::GlobalAsm { .. }
|
||||
| hir::ItemKind::ForeignMod { .. }
|
||||
| hir::ItemKind::Mod(..)
|
||||
| hir::ItemKind::Macro(..)
|
||||
|
|
|
|||
|
|
@ -47,6 +47,9 @@ metadata_crate_dep_rustc_driver =
|
|||
metadata_crate_location_unknown_type =
|
||||
extern location for {$crate_name} is of an unknown type: {$path}
|
||||
|
||||
metadata_crate_not_compiler_builtins =
|
||||
the crate `{$crate_name}` resolved as `compiler_builtins` but is not `#![compiler_builtins]`
|
||||
|
||||
metadata_crate_not_panic_runtime =
|
||||
the crate `{$crate_name}` is not a panic runtime
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ use rustc_session::lint::{self, BuiltinLintDiag};
|
|||
use rustc_session::output::validate_crate_name;
|
||||
use rustc_session::search_paths::PathKind;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::{DUMMY_SP, Ident, STDLIB_STABLE_CRATES, Span, Symbol, sym};
|
||||
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym};
|
||||
use rustc_target::spec::{PanicStrategy, Target, TargetTuple};
|
||||
use tracing::{debug, info, trace};
|
||||
|
||||
|
|
@ -147,6 +147,7 @@ impl<'a> std::fmt::Debug for CrateDump<'a> {
|
|||
writeln!(fmt, " cnum: {cnum}")?;
|
||||
writeln!(fmt, " hash: {}", data.hash())?;
|
||||
writeln!(fmt, " reqd: {:?}", data.dep_kind())?;
|
||||
writeln!(fmt, " priv: {:?}", data.is_private_dep())?;
|
||||
let CrateSource { dylib, rlib, rmeta } = data.source();
|
||||
if let Some(dylib) = dylib {
|
||||
writeln!(fmt, " dylib: {}", dylib.0.display())?;
|
||||
|
|
@ -162,6 +163,53 @@ impl<'a> std::fmt::Debug for CrateDump<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Reason that a crate is being sourced as a dependency.
|
||||
#[derive(Clone, Copy)]
|
||||
enum CrateOrigin<'a> {
|
||||
/// This crate was a dependency of another crate.
|
||||
IndirectDependency {
|
||||
/// Where this dependency was included from.
|
||||
dep_root: &'a CratePaths,
|
||||
/// True if the parent is private, meaning the dependent should also be private.
|
||||
parent_private: bool,
|
||||
/// Dependency info about this crate.
|
||||
dep: &'a CrateDep,
|
||||
},
|
||||
/// Injected by `rustc`.
|
||||
Injected,
|
||||
/// Provided by `extern crate foo` or as part of the extern prelude.
|
||||
Extern,
|
||||
}
|
||||
|
||||
impl<'a> CrateOrigin<'a> {
|
||||
/// Return the dependency root, if any.
|
||||
fn dep_root(&self) -> Option<&'a CratePaths> {
|
||||
match self {
|
||||
CrateOrigin::IndirectDependency { dep_root, .. } => Some(dep_root),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return dependency information, if any.
|
||||
fn dep(&self) -> Option<&'a CrateDep> {
|
||||
match self {
|
||||
CrateOrigin::IndirectDependency { dep, .. } => Some(dep),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// `Some(true)` if the dependency is private or its parent is private, `Some(false)` if the
|
||||
/// dependency is not private, `None` if it could not be determined.
|
||||
fn private_dep(&self) -> Option<bool> {
|
||||
match self {
|
||||
CrateOrigin::IndirectDependency { parent_private, dep, .. } => {
|
||||
Some(dep.is_private || *parent_private)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CStore {
|
||||
pub fn from_tcx(tcx: TyCtxt<'_>) -> FreezeReadGuard<'_, CStore> {
|
||||
FreezeReadGuard::map(tcx.untracked().cstore.read(), |cstore| {
|
||||
|
|
@ -497,25 +545,13 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
|||
&self,
|
||||
name: Symbol,
|
||||
private_dep: Option<bool>,
|
||||
dep_root: Option<&CratePaths>,
|
||||
origin: CrateOrigin<'_>,
|
||||
) -> bool {
|
||||
// Standard library crates are never private.
|
||||
if STDLIB_STABLE_CRATES.contains(&name) {
|
||||
tracing::info!("returning false for {name} is private");
|
||||
return false;
|
||||
}
|
||||
|
||||
let extern_private = self.sess.opts.externs.get(name.as_str()).map(|e| e.is_private_dep);
|
||||
|
||||
// Any descendants of `std` should be private. These crates are usually not marked
|
||||
// private in metadata, so we ignore that field.
|
||||
if extern_private.is_none()
|
||||
&& let Some(dep) = dep_root
|
||||
&& STDLIB_STABLE_CRATES.contains(&dep.name)
|
||||
{
|
||||
if matches!(origin, CrateOrigin::Injected) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let extern_private = self.sess.opts.externs.get(name.as_str()).map(|e| e.is_private_dep);
|
||||
match (extern_private, private_dep) {
|
||||
// Explicit non-private via `--extern`, explicit non-private from metadata, or
|
||||
// unspecified with default to public.
|
||||
|
|
@ -528,7 +564,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
|||
fn register_crate(
|
||||
&mut self,
|
||||
host_lib: Option<Library>,
|
||||
dep_root: Option<&CratePaths>,
|
||||
origin: CrateOrigin<'_>,
|
||||
lib: Library,
|
||||
dep_kind: CrateDepKind,
|
||||
name: Symbol,
|
||||
|
|
@ -540,7 +576,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
|||
let Library { source, metadata } = lib;
|
||||
let crate_root = metadata.get_root();
|
||||
let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash());
|
||||
let private_dep = self.is_private_dep(name, private_dep, dep_root);
|
||||
let private_dep = self.is_private_dep(name, private_dep, origin);
|
||||
|
||||
// Claim this crate number and cache it
|
||||
let feed = self.cstore.intern_stable_crate_id(&crate_root, self.tcx)?;
|
||||
|
|
@ -556,14 +592,15 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
|||
// Maintain a reference to the top most crate.
|
||||
// Stash paths for top-most crate locally if necessary.
|
||||
let crate_paths;
|
||||
let dep_root = if let Some(dep_root) = dep_root {
|
||||
let dep_root = if let Some(dep_root) = origin.dep_root() {
|
||||
dep_root
|
||||
} else {
|
||||
crate_paths = CratePaths::new(crate_root.name(), source.clone());
|
||||
&crate_paths
|
||||
};
|
||||
|
||||
let cnum_map = self.resolve_crate_deps(dep_root, &crate_root, &metadata, cnum, dep_kind)?;
|
||||
let cnum_map =
|
||||
self.resolve_crate_deps(dep_root, &crate_root, &metadata, cnum, dep_kind, private_dep)?;
|
||||
|
||||
let raw_proc_macros = if crate_root.is_proc_macro_crate() {
|
||||
let temp_root;
|
||||
|
|
@ -664,17 +701,19 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
|||
name: Symbol,
|
||||
span: Span,
|
||||
dep_kind: CrateDepKind,
|
||||
origin: CrateOrigin<'_>,
|
||||
) -> Option<CrateNum> {
|
||||
self.used_extern_options.insert(name);
|
||||
match self.maybe_resolve_crate(name, dep_kind, None) {
|
||||
match self.maybe_resolve_crate(name, dep_kind, origin) {
|
||||
Ok(cnum) => {
|
||||
self.cstore.set_used_recursively(cnum);
|
||||
Some(cnum)
|
||||
}
|
||||
Err(err) => {
|
||||
debug!("failed to resolve crate {} {:?}", name, dep_kind);
|
||||
let missing_core =
|
||||
self.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, None).is_err();
|
||||
let missing_core = self
|
||||
.maybe_resolve_crate(sym::core, CrateDepKind::Explicit, CrateOrigin::Extern)
|
||||
.is_err();
|
||||
err.report(self.sess, span, missing_core);
|
||||
None
|
||||
}
|
||||
|
|
@ -685,20 +724,20 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
|||
&'b mut self,
|
||||
name: Symbol,
|
||||
mut dep_kind: CrateDepKind,
|
||||
dep_of: Option<(&'b CratePaths, &'b CrateDep)>,
|
||||
origin: CrateOrigin<'b>,
|
||||
) -> Result<CrateNum, CrateError> {
|
||||
info!("resolving crate `{}`", name);
|
||||
if !name.as_str().is_ascii() {
|
||||
return Err(CrateError::NonAsciiName(name));
|
||||
}
|
||||
|
||||
let dep_root = dep_of.map(|d| d.0);
|
||||
let dep = dep_of.map(|d| d.1);
|
||||
let dep_root = origin.dep_root();
|
||||
let dep = origin.dep();
|
||||
let hash = dep.map(|d| d.hash);
|
||||
let host_hash = dep.map(|d| d.host_hash).flatten();
|
||||
let extra_filename = dep.map(|d| &d.extra_filename[..]);
|
||||
let path_kind = if dep.is_some() { PathKind::Dependency } else { PathKind::Crate };
|
||||
let private_dep = dep.map(|d| d.is_private);
|
||||
let private_dep = origin.private_dep();
|
||||
|
||||
let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) {
|
||||
(LoadResult::Previous(cnum), None)
|
||||
|
|
@ -731,12 +770,12 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
|||
|
||||
match result {
|
||||
(LoadResult::Previous(cnum), None) => {
|
||||
info!("library for `{}` was loaded previously", name);
|
||||
info!("library for `{}` was loaded previously, cnum {cnum}", name);
|
||||
// When `private_dep` is none, it indicates the directly dependent crate. If it is
|
||||
// not specified by `--extern` on command line parameters, it may be
|
||||
// `private-dependency` when `register_crate` is called for the first time. Then it must be updated to
|
||||
// `public-dependency` here.
|
||||
let private_dep = self.is_private_dep(name, private_dep, dep_root);
|
||||
let private_dep = self.is_private_dep(name, private_dep, origin);
|
||||
let data = self.cstore.get_crate_data_mut(cnum);
|
||||
if data.is_proc_macro_crate() {
|
||||
dep_kind = CrateDepKind::MacrosOnly;
|
||||
|
|
@ -747,7 +786,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
|||
}
|
||||
(LoadResult::Loaded(library), host_library) => {
|
||||
info!("register newly loaded library for `{}`", name);
|
||||
self.register_crate(host_library, dep_root, library, dep_kind, name, private_dep)
|
||||
self.register_crate(host_library, origin, library, dep_kind, name, private_dep)
|
||||
}
|
||||
_ => panic!(),
|
||||
}
|
||||
|
|
@ -783,6 +822,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
|||
metadata: &MetadataBlob,
|
||||
krate: CrateNum,
|
||||
dep_kind: CrateDepKind,
|
||||
parent_is_private: bool,
|
||||
) -> Result<CrateNumMap, CrateError> {
|
||||
debug!(
|
||||
"resolving deps of external crate `{}` with dep root `{}`",
|
||||
|
|
@ -801,17 +841,26 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
|||
crate_num_map.push(krate);
|
||||
for dep in deps {
|
||||
info!(
|
||||
"resolving dep `{}`->`{}` hash: `{}` extra filename: `{}`",
|
||||
"resolving dep `{}`->`{}` hash: `{}` extra filename: `{}` private {}",
|
||||
crate_root.name(),
|
||||
dep.name,
|
||||
dep.hash,
|
||||
dep.extra_filename
|
||||
dep.extra_filename,
|
||||
dep.is_private,
|
||||
);
|
||||
let dep_kind = match dep_kind {
|
||||
CrateDepKind::MacrosOnly => CrateDepKind::MacrosOnly,
|
||||
_ => dep.kind,
|
||||
};
|
||||
let cnum = self.maybe_resolve_crate(dep.name, dep_kind, Some((dep_root, &dep)))?;
|
||||
let cnum = self.maybe_resolve_crate(
|
||||
dep.name,
|
||||
dep_kind,
|
||||
CrateOrigin::IndirectDependency {
|
||||
dep_root,
|
||||
parent_private: parent_is_private,
|
||||
dep: &dep,
|
||||
},
|
||||
)?;
|
||||
crate_num_map.push(cnum);
|
||||
}
|
||||
|
||||
|
|
@ -905,7 +954,9 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
|||
};
|
||||
info!("panic runtime not found -- loading {}", name);
|
||||
|
||||
let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else {
|
||||
let Some(cnum) =
|
||||
self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, CrateOrigin::Injected)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let data = self.cstore.get_crate_data(cnum);
|
||||
|
|
@ -934,7 +985,9 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
|||
info!("loading profiler");
|
||||
|
||||
let name = Symbol::intern(&self.sess.opts.unstable_opts.profiler_runtime);
|
||||
let Some(cnum) = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit) else {
|
||||
let Some(cnum) =
|
||||
self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, CrateOrigin::Injected)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
let data = self.cstore.get_crate_data(cnum);
|
||||
|
|
@ -1047,12 +1100,54 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
|||
if entry.force {
|
||||
let name_interned = Symbol::intern(name);
|
||||
if !self.used_extern_options.contains(&name_interned) {
|
||||
self.resolve_crate(name_interned, DUMMY_SP, CrateDepKind::Explicit);
|
||||
self.resolve_crate(
|
||||
name_interned,
|
||||
DUMMY_SP,
|
||||
CrateDepKind::Explicit,
|
||||
CrateOrigin::Extern,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Inject the `compiler_builtins` crate if it is not already in the graph.
|
||||
fn inject_compiler_builtins(&mut self, krate: &ast::Crate) {
|
||||
// `compiler_builtins` does not get extern builtins, nor do `#![no_core]` crates
|
||||
if attr::contains_name(&krate.attrs, sym::compiler_builtins)
|
||||
|| attr::contains_name(&krate.attrs, sym::no_core)
|
||||
{
|
||||
info!("`compiler_builtins` unneeded");
|
||||
return;
|
||||
}
|
||||
|
||||
// If a `#![compiler_builtins]` crate already exists, avoid injecting it twice. This is
|
||||
// the common case since usually it appears as a dependency of `std` or `alloc`.
|
||||
for (cnum, cmeta) in self.cstore.iter_crate_data() {
|
||||
if cmeta.is_compiler_builtins() {
|
||||
info!("`compiler_builtins` already exists (cnum = {cnum}); skipping injection");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// `compiler_builtins` is not yet in the graph; inject it. Error on resolution failure.
|
||||
let Some(cnum) = self.resolve_crate(
|
||||
sym::compiler_builtins,
|
||||
krate.spans.inner_span.shrink_to_lo(),
|
||||
CrateDepKind::Explicit,
|
||||
CrateOrigin::Injected,
|
||||
) else {
|
||||
info!("`compiler_builtins` not resolved");
|
||||
return;
|
||||
};
|
||||
|
||||
// Sanity check that the loaded crate is `#![compiler_builtins]`
|
||||
let cmeta = self.cstore.get_crate_data(cnum);
|
||||
if !cmeta.is_compiler_builtins() {
|
||||
self.dcx().emit_err(errors::CrateNotCompilerBuiltins { crate_name: cmeta.name() });
|
||||
}
|
||||
}
|
||||
|
||||
fn inject_dependency_if(
|
||||
&mut self,
|
||||
krate: CrateNum,
|
||||
|
|
@ -1162,6 +1257,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
|||
}
|
||||
|
||||
pub fn postprocess(&mut self, krate: &ast::Crate) {
|
||||
self.inject_compiler_builtins(krate);
|
||||
self.inject_forced_externs();
|
||||
self.inject_profiler_runtime();
|
||||
self.inject_allocator_crate(krate);
|
||||
|
|
@ -1173,6 +1269,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
|||
info!("{:?}", CrateDump(self.cstore));
|
||||
}
|
||||
|
||||
/// Process an `extern crate foo` AST node.
|
||||
pub fn process_extern_crate(
|
||||
&mut self,
|
||||
item: &ast::Item,
|
||||
|
|
@ -1198,7 +1295,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
|||
CrateDepKind::Explicit
|
||||
};
|
||||
|
||||
let cnum = self.resolve_crate(name, item.span, dep_kind)?;
|
||||
let cnum = self.resolve_crate(name, item.span, dep_kind, CrateOrigin::Extern)?;
|
||||
|
||||
let path_len = definitions.def_path(def_id).data.len();
|
||||
self.cstore.update_extern_crate(
|
||||
|
|
@ -1217,7 +1314,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
|||
}
|
||||
|
||||
pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> Option<CrateNum> {
|
||||
let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit)?;
|
||||
let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit, CrateOrigin::Extern)?;
|
||||
|
||||
self.cstore.update_extern_crate(
|
||||
cnum,
|
||||
|
|
@ -1234,7 +1331,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
|||
}
|
||||
|
||||
pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option<CrateNum> {
|
||||
self.maybe_resolve_crate(name, CrateDepKind::Explicit, None).ok()
|
||||
self.maybe_resolve_crate(name, CrateDepKind::Explicit, CrateOrigin::Extern).ok()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -332,6 +332,12 @@ pub struct CrateNotPanicRuntime {
|
|||
pub crate_name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_crate_not_compiler_builtins)]
|
||||
pub struct CrateNotCompilerBuiltins {
|
||||
pub crate_name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_no_panic_strategy)]
|
||||
pub struct NoPanicStrategy {
|
||||
|
|
|
|||
|
|
@ -260,7 +260,7 @@ pub(crate) struct CrateLocator<'a> {
|
|||
crate_rejections: CrateRejections,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct CratePaths {
|
||||
pub(crate) name: Symbol,
|
||||
source: CrateSource,
|
||||
|
|
@ -272,7 +272,7 @@ impl CratePaths {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub(crate) enum CrateFlavor {
|
||||
Rlib,
|
||||
Rmeta,
|
||||
|
|
@ -893,13 +893,13 @@ fn get_flavor_from_path(path: &Path) -> CrateFlavor {
|
|||
|
||||
// ------------------------------------------ Error reporting -------------------------------------
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
struct CrateMismatch {
|
||||
path: PathBuf,
|
||||
got: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct CrateRejections {
|
||||
via_hash: Vec<CrateMismatch>,
|
||||
via_triple: Vec<CrateMismatch>,
|
||||
|
|
@ -912,6 +912,7 @@ struct CrateRejections {
|
|||
/// Candidate rejection reasons collected during crate search.
|
||||
/// If no candidate is accepted, then these reasons are presented to the user,
|
||||
/// otherwise they are ignored.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct CombinedLocatorError {
|
||||
crate_name: Symbol,
|
||||
dep_root: Option<CratePaths>,
|
||||
|
|
@ -921,6 +922,7 @@ pub(crate) struct CombinedLocatorError {
|
|||
crate_rejections: CrateRejections,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum CrateError {
|
||||
NonAsciiName(Symbol),
|
||||
ExternLocationNotExist(Symbol, PathBuf),
|
||||
|
|
|
|||
|
|
@ -1936,6 +1936,10 @@ impl CrateMetadata {
|
|||
self.root.needs_panic_runtime
|
||||
}
|
||||
|
||||
pub(crate) fn is_private_dep(&self) -> bool {
|
||||
self.private_dep
|
||||
}
|
||||
|
||||
pub(crate) fn is_panic_runtime(&self) -> bool {
|
||||
self.root.panic_runtime
|
||||
}
|
||||
|
|
@ -1944,6 +1948,10 @@ impl CrateMetadata {
|
|||
self.root.profiler_runtime
|
||||
}
|
||||
|
||||
pub(crate) fn is_compiler_builtins(&self) -> bool {
|
||||
self.root.compiler_builtins
|
||||
}
|
||||
|
||||
pub(crate) fn needs_allocator(&self) -> bool {
|
||||
self.root.needs_allocator
|
||||
}
|
||||
|
|
|
|||
|
|
@ -305,6 +305,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
DefKind::Static { safety: _, mutability, nested: false } => {
|
||||
BodyOwnerKind::Static(mutability)
|
||||
}
|
||||
DefKind::GlobalAsm => BodyOwnerKind::GlobalAsm,
|
||||
dk => bug!("{:?} is not a body node: {:?}", def_id, dk),
|
||||
}
|
||||
}
|
||||
|
|
@ -327,7 +328,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
ConstContext::ConstFn
|
||||
}
|
||||
BodyOwnerKind::Fn if self.is_const_default_method(def_id) => ConstContext::ConstFn,
|
||||
BodyOwnerKind::Fn | BodyOwnerKind::Closure => return None,
|
||||
BodyOwnerKind::Fn | BodyOwnerKind::Closure | BodyOwnerKind::GlobalAsm => return None,
|
||||
};
|
||||
|
||||
Some(ccx)
|
||||
|
|
@ -1166,7 +1167,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
|
|||
ItemKind::Macro(..) => "macro",
|
||||
ItemKind::Mod(..) => "mod",
|
||||
ItemKind::ForeignMod { .. } => "foreign mod",
|
||||
ItemKind::GlobalAsm(..) => "global asm",
|
||||
ItemKind::GlobalAsm { .. } => "global asm",
|
||||
ItemKind::TyAlias(..) => "ty",
|
||||
ItemKind::Enum(..) => "enum",
|
||||
ItemKind::Struct(..) => "struct",
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ thir_with_elements! {
|
|||
pub enum BodyTy<'tcx> {
|
||||
Const(Ty<'tcx>),
|
||||
Fn(FnSig<'tcx>),
|
||||
GlobalAsm(Ty<'tcx>),
|
||||
}
|
||||
|
||||
/// Description of a type-checked function parameter.
|
||||
|
|
@ -605,8 +606,7 @@ pub enum InlineAsmOperand<'tcx> {
|
|||
span: Span,
|
||||
},
|
||||
SymFn {
|
||||
value: mir::Const<'tcx>,
|
||||
span: Span,
|
||||
value: ExprId,
|
||||
},
|
||||
SymStatic {
|
||||
def_id: DefId,
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
|
|||
}
|
||||
Out { expr: None, reg: _, late: _ }
|
||||
| Const { value: _, span: _ }
|
||||
| SymFn { value: _, span: _ }
|
||||
| SymFn { value: _ }
|
||||
| SymStatic { def_id: _ } => {}
|
||||
Label { block } => visitor.visit_block(&visitor.thir()[*block]),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1472,7 +1472,11 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
self.codegen_fn_attrs(def_id)
|
||||
} else if matches!(
|
||||
def_kind,
|
||||
DefKind::AnonConst | DefKind::AssocConst | DefKind::Const | DefKind::InlineConst
|
||||
DefKind::AnonConst
|
||||
| DefKind::AssocConst
|
||||
| DefKind::Const
|
||||
| DefKind::InlineConst
|
||||
| DefKind::GlobalAsm
|
||||
) {
|
||||
CodegenFnAttrs::EMPTY
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -482,15 +482,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
}),
|
||||
}
|
||||
}
|
||||
thir::InlineAsmOperand::SymFn { value, span } => {
|
||||
mir::InlineAsmOperand::SymFn {
|
||||
value: Box::new(ConstOperand {
|
||||
span,
|
||||
user_ty: None,
|
||||
const_: value,
|
||||
}),
|
||||
}
|
||||
}
|
||||
thir::InlineAsmOperand::SymFn { value } => mir::InlineAsmOperand::SymFn {
|
||||
value: Box::new(this.as_constant(&this.thir[value])),
|
||||
},
|
||||
thir::InlineAsmOperand::SymStatic { def_id } => {
|
||||
mir::InlineAsmOperand::SymStatic { def_id }
|
||||
}
|
||||
|
|
@ -518,10 +512,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
}
|
||||
|
||||
let asm_macro = match asm_macro {
|
||||
AsmMacro::Asm => InlineAsmMacro::Asm,
|
||||
AsmMacro::GlobalAsm => {
|
||||
span_bug!(expr_span, "unexpected global_asm! in inline asm")
|
||||
}
|
||||
AsmMacro::Asm | AsmMacro::GlobalAsm => InlineAsmMacro::Asm,
|
||||
AsmMacro::NakedAsm => InlineAsmMacro::NakedAsm,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,9 @@ pub fn build_mir<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Body<'tcx> {
|
|||
Ok((thir, expr)) => {
|
||||
let build_mir = |thir: &Thir<'tcx>| match thir.body_type {
|
||||
thir::BodyTy::Fn(fn_sig) => construct_fn(tcx, def, thir, expr, fn_sig),
|
||||
thir::BodyTy::Const(ty) => construct_const(tcx, def, thir, expr, ty),
|
||||
thir::BodyTy::Const(ty) | thir::BodyTy::GlobalAsm(ty) => {
|
||||
construct_const(tcx, def, thir, expr, ty)
|
||||
}
|
||||
};
|
||||
|
||||
// this must run before MIR dump, because
|
||||
|
|
@ -576,6 +578,7 @@ fn construct_const<'a, 'tcx>(
|
|||
let span = tcx.def_span(def);
|
||||
(span, span)
|
||||
}
|
||||
Node::Item(hir::Item { kind: hir::ItemKind::GlobalAsm { .. }, span, .. }) => (*span, *span),
|
||||
_ => span_bug!(tcx.def_span(def), "can't build MIR for {:?}", def),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use std::borrow::Cow;
|
|||
use std::mem;
|
||||
use std::ops::Bound;
|
||||
|
||||
use rustc_ast::AsmMacro;
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_errors::DiagArgValue;
|
||||
use rustc_hir::def::DefKind;
|
||||
|
|
@ -559,7 +560,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
ExprKind::InlineAsm(box InlineAsmExpr {
|
||||
asm_macro: _,
|
||||
asm_macro: AsmMacro::Asm | AsmMacro::NakedAsm,
|
||||
ref operands,
|
||||
template: _,
|
||||
options: _,
|
||||
|
|
@ -583,7 +584,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
|
|||
}
|
||||
Out { expr: None, reg: _, late: _ }
|
||||
| Const { value: _, span: _ }
|
||||
| SymFn { value: _, span: _ }
|
||||
| SymFn { value: _ }
|
||||
| SymStatic { def_id: _ } => {}
|
||||
Label { block } => {
|
||||
// Label blocks are safe context.
|
||||
|
|
|
|||
|
|
@ -737,13 +737,8 @@ impl<'tcx> ThirBuildCx<'tcx> {
|
|||
|
||||
InlineAsmOperand::Const { value, span }
|
||||
}
|
||||
hir::InlineAsmOperand::SymFn { ref anon_const } => {
|
||||
let value =
|
||||
mir::Const::from_unevaluated(tcx, anon_const.def_id.to_def_id())
|
||||
.instantiate_identity();
|
||||
let span = tcx.def_span(anon_const.def_id);
|
||||
|
||||
InlineAsmOperand::SymFn { value, span }
|
||||
hir::InlineAsmOperand::SymFn { expr } => {
|
||||
InlineAsmOperand::SymFn { value: self.mirror_expr(expr) }
|
||||
}
|
||||
hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
|
||||
InlineAsmOperand::SymStatic { def_id }
|
||||
|
|
|
|||
|
|
@ -76,23 +76,29 @@ impl<'tcx> ThirBuildCx<'tcx> {
|
|||
let hir = tcx.hir();
|
||||
let hir_id = tcx.local_def_id_to_hir_id(def);
|
||||
|
||||
let body_type = if tcx.hir_body_owner_kind(def).is_fn_or_closure() {
|
||||
// fetch the fully liberated fn signature (that is, all bound
|
||||
// types/lifetimes replaced)
|
||||
BodyTy::Fn(typeck_results.liberated_fn_sigs()[hir_id])
|
||||
} else {
|
||||
// Get the revealed type of this const. This is *not* the adjusted
|
||||
// type of its body, which may be a subtype of this type. For
|
||||
// example:
|
||||
//
|
||||
// fn foo(_: &()) {}
|
||||
// static X: fn(&'static ()) = foo;
|
||||
//
|
||||
// The adjusted type of the body of X is `for<'a> fn(&'a ())` which
|
||||
// is not the same as the type of X. We need the type of the return
|
||||
// place to be the type of the constant because NLL typeck will
|
||||
// equate them.
|
||||
BodyTy::Const(typeck_results.node_type(hir_id))
|
||||
let body_type = match tcx.hir_body_owner_kind(def) {
|
||||
rustc_hir::BodyOwnerKind::Fn | rustc_hir::BodyOwnerKind::Closure => {
|
||||
// fetch the fully liberated fn signature (that is, all bound
|
||||
// types/lifetimes replaced)
|
||||
BodyTy::Fn(typeck_results.liberated_fn_sigs()[hir_id])
|
||||
}
|
||||
rustc_hir::BodyOwnerKind::Const { .. } | rustc_hir::BodyOwnerKind::Static(_) => {
|
||||
// Get the revealed type of this const. This is *not* the adjusted
|
||||
// type of its body, which may be a subtype of this type. For
|
||||
// example:
|
||||
//
|
||||
// fn foo(_: &()) {}
|
||||
// static X: fn(&'static ()) = foo;
|
||||
//
|
||||
// The adjusted type of the body of X is `for<'a> fn(&'a ())` which
|
||||
// is not the same as the type of X. We need the type of the return
|
||||
// place to be the type of the constant because NLL typeck will
|
||||
// equate them.
|
||||
BodyTy::Const(typeck_results.node_type(hir_id))
|
||||
}
|
||||
rustc_hir::BodyOwnerKind::GlobalAsm => {
|
||||
BodyTy::GlobalAsm(typeck_results.node_type(hir_id))
|
||||
}
|
||||
};
|
||||
|
||||
Self {
|
||||
|
|
|
|||
|
|
@ -921,10 +921,10 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
|
|||
print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
|
||||
print_indented!(self, "}", depth_lvl + 1);
|
||||
}
|
||||
InlineAsmOperand::SymFn { value, span } => {
|
||||
InlineAsmOperand::SymFn { value } => {
|
||||
print_indented!(self, "InlineAsmOperand::SymFn {", depth_lvl);
|
||||
print_indented!(self, format!("value: {:?}", *value), depth_lvl + 1);
|
||||
print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
|
||||
print_indented!(self, "value: ", depth_lvl + 1);
|
||||
self.print_expr(*value, depth_lvl + 2);
|
||||
print_indented!(self, "}", depth_lvl + 1);
|
||||
}
|
||||
InlineAsmOperand::SymStatic { def_id } => {
|
||||
|
|
|
|||
|
|
@ -479,24 +479,23 @@ fn collect_items_rec<'tcx>(
|
|||
recursion_depth_reset = None;
|
||||
|
||||
let item = tcx.hir_item(item_id);
|
||||
if let hir::ItemKind::GlobalAsm(asm) = item.kind {
|
||||
if let hir::ItemKind::GlobalAsm { asm, .. } = item.kind {
|
||||
for (op, op_sp) in asm.operands {
|
||||
match op {
|
||||
match *op {
|
||||
hir::InlineAsmOperand::Const { .. } => {
|
||||
// Only constants which resolve to a plain integer
|
||||
// are supported. Therefore the value should not
|
||||
// depend on any other items.
|
||||
}
|
||||
hir::InlineAsmOperand::SymFn { anon_const } => {
|
||||
let fn_ty =
|
||||
tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
|
||||
hir::InlineAsmOperand::SymFn { expr } => {
|
||||
let fn_ty = tcx.typeck(item_id.owner_id).expr_ty(expr);
|
||||
visit_fn_use(tcx, fn_ty, false, *op_sp, &mut used_items);
|
||||
}
|
||||
hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
|
||||
let instance = Instance::mono(tcx, *def_id);
|
||||
let instance = Instance::mono(tcx, def_id);
|
||||
if tcx.should_codegen_locally(instance) {
|
||||
trace!("collecting static {:?}", def_id);
|
||||
used_items.push(dummy_spanned(MonoItem::Static(*def_id)));
|
||||
used_items.push(dummy_spanned(MonoItem::Static(def_id)));
|
||||
}
|
||||
}
|
||||
hir::InlineAsmOperand::In { .. }
|
||||
|
|
|
|||
|
|
@ -246,7 +246,7 @@ impl<'tcx> ReachableContext<'tcx> {
|
|||
| hir::ItemKind::Struct(..)
|
||||
| hir::ItemKind::Enum(..)
|
||||
| hir::ItemKind::Union(..)
|
||||
| hir::ItemKind::GlobalAsm(..) => {}
|
||||
| hir::ItemKind::GlobalAsm { .. } => {}
|
||||
}
|
||||
}
|
||||
Node::TraitItem(trait_method) => {
|
||||
|
|
|
|||
|
|
@ -645,7 +645,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
|
|||
// The interface is empty, and no nested items.
|
||||
hir::ItemKind::Use(..)
|
||||
| hir::ItemKind::ExternCrate(..)
|
||||
| hir::ItemKind::GlobalAsm(..) => {}
|
||||
| hir::ItemKind::GlobalAsm { .. } => {}
|
||||
// The interface is empty, and all nested items are processed by `visit_item`.
|
||||
hir::ItemKind::Mod(..) => {}
|
||||
hir::ItemKind::Macro(macro_def, _) => {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
#![feature(core_intrinsics)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(never_type)]
|
||||
#![feature(ptr_sub_ptr)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![warn(unreachable_pub)]
|
||||
// tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -547,12 +547,15 @@ fn layout_of_uncached<'tcx>(
|
|||
(
|
||||
BackendRepr::Memory { sized: true },
|
||||
AbiAndPrefAlign {
|
||||
abi: Align::max_for_offset(size),
|
||||
pref: dl.vector_align(size).pref,
|
||||
abi: Align::max_aligned_factor(size),
|
||||
pref: dl.llvmlike_vector_align(size).pref,
|
||||
},
|
||||
)
|
||||
} else {
|
||||
(BackendRepr::Vector { element: e_abi, count: e_len }, dl.vector_align(size))
|
||||
(
|
||||
BackendRepr::Vector { element: e_abi, count: e_len },
|
||||
dl.llvmlike_vector_align(size),
|
||||
)
|
||||
};
|
||||
let size = size.align_to(align.abi);
|
||||
|
||||
|
|
|
|||
|
|
@ -69,31 +69,30 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou
|
|||
}
|
||||
|
||||
fn check_layout_abi<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) {
|
||||
// Verify the ABI mandated alignment and size.
|
||||
let align = layout.backend_repr.inherent_align(cx).map(|align| align.abi);
|
||||
let size = layout.backend_repr.inherent_size(cx);
|
||||
let Some((align, size)) = align.zip(size) else {
|
||||
assert_matches!(
|
||||
layout.layout.backend_repr(),
|
||||
BackendRepr::Memory { .. },
|
||||
"ABI unexpectedly missing alignment and/or size in {layout:#?}"
|
||||
// Verify the ABI-mandated alignment and size for scalars.
|
||||
let align = layout.backend_repr.scalar_align(cx);
|
||||
let size = layout.backend_repr.scalar_size(cx);
|
||||
if let Some(align) = align {
|
||||
assert_eq!(
|
||||
layout.layout.align().abi,
|
||||
align,
|
||||
"alignment mismatch between ABI and layout in {layout:#?}"
|
||||
);
|
||||
return;
|
||||
};
|
||||
assert_eq!(
|
||||
layout.layout.align().abi,
|
||||
align,
|
||||
"alignment mismatch between ABI and layout in {layout:#?}"
|
||||
);
|
||||
assert_eq!(
|
||||
layout.layout.size(),
|
||||
size,
|
||||
"size mismatch between ABI and layout in {layout:#?}"
|
||||
);
|
||||
}
|
||||
if let Some(size) = size {
|
||||
assert_eq!(
|
||||
layout.layout.size(),
|
||||
size,
|
||||
"size mismatch between ABI and layout in {layout:#?}"
|
||||
);
|
||||
}
|
||||
|
||||
// Verify per-ABI invariants
|
||||
match layout.layout.backend_repr() {
|
||||
BackendRepr::Scalar(_) => {
|
||||
// These must always be present for `Scalar` types.
|
||||
let align = align.unwrap();
|
||||
let size = size.unwrap();
|
||||
// Check that this matches the underlying field.
|
||||
let inner = skip_newtypes(cx, layout);
|
||||
assert!(
|
||||
|
|
@ -235,9 +234,15 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou
|
|||
"`ScalarPair` second field with bad ABI in {inner:#?}",
|
||||
);
|
||||
}
|
||||
BackendRepr::Vector { element, .. } => {
|
||||
assert!(align >= element.align(cx).abi); // just sanity-checking `vector_align`.
|
||||
// FIXME: Do some kind of check of the inner type, like for Scalar and ScalarPair.
|
||||
BackendRepr::Vector { element, count } => {
|
||||
let align = layout.align.abi;
|
||||
let size = layout.size;
|
||||
let element_align = element.align(cx).abi;
|
||||
let element_size = element.size(cx);
|
||||
// Currently, vectors must always be aligned to at least their elements:
|
||||
assert!(align >= element_align);
|
||||
// And the size has to be element * count plus alignment padding, of course
|
||||
assert!(size == (element_size * count).align_to(align));
|
||||
}
|
||||
BackendRepr::Memory { .. } => {} // Nothing to check.
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
cargo-features = ["public-dependency"]
|
||||
|
||||
[package]
|
||||
name = "alloc"
|
||||
version = "0.0.0"
|
||||
|
|
@ -9,7 +11,7 @@ autobenches = false
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
core = { path = "../core" }
|
||||
core = { path = "../core", public = true }
|
||||
compiler_builtins = { version = "=0.1.146", features = ['rustc-dep-of-std'] }
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
|||
|
|
@ -137,7 +137,6 @@
|
|||
#![feature(pointer_like_trait)]
|
||||
#![feature(ptr_internals)]
|
||||
#![feature(ptr_metadata)]
|
||||
#![feature(ptr_sub_ptr)]
|
||||
#![feature(set_ptr_value)]
|
||||
#![feature(sized_type_properties)]
|
||||
#![feature(slice_from_ptr_range)]
|
||||
|
|
|
|||
|
|
@ -3675,6 +3675,7 @@ pub const unsafe fn ptr_offset_from<T>(_ptr: *const T, _base: *const T) -> isize
|
|||
#[rustc_nounwind]
|
||||
#[rustc_intrinsic]
|
||||
#[rustc_intrinsic_must_be_overridden]
|
||||
#[rustc_intrinsic_const_stable_indirect]
|
||||
pub const unsafe fn ptr_offset_from_unsigned<T>(_ptr: *const T, _base: *const T) -> usize {
|
||||
unimplemented!()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3320,14 +3320,14 @@ macro_rules! uint_impl {
|
|||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(unsigned_is_multiple_of)]
|
||||
#[doc = concat!("assert!(6_", stringify!($SelfT), ".is_multiple_of(2));")]
|
||||
#[doc = concat!("assert!(!5_", stringify!($SelfT), ".is_multiple_of(2));")]
|
||||
///
|
||||
#[doc = concat!("assert!(0_", stringify!($SelfT), ".is_multiple_of(0));")]
|
||||
#[doc = concat!("assert!(!6_", stringify!($SelfT), ".is_multiple_of(0));")]
|
||||
/// ```
|
||||
#[unstable(feature = "unsigned_is_multiple_of", issue = "128101")]
|
||||
#[stable(feature = "unsigned_is_multiple_of", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "unsigned_is_multiple_of", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use]
|
||||
#[inline]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
|
|
|
|||
|
|
@ -723,7 +723,6 @@ impl<T: ?Sized> *const T {
|
|||
/// to [`sub`](#method.sub)). The following are all equivalent, assuming
|
||||
/// that their safety preconditions are met:
|
||||
/// ```rust
|
||||
/// # #![feature(ptr_sub_ptr)]
|
||||
/// # unsafe fn blah(ptr: *const i32, origin: *const i32, count: usize) -> bool { unsafe {
|
||||
/// ptr.sub_ptr(origin) == count
|
||||
/// # &&
|
||||
|
|
@ -752,8 +751,6 @@ impl<T: ?Sized> *const T {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(ptr_sub_ptr)]
|
||||
///
|
||||
/// let a = [0; 5];
|
||||
/// let ptr1: *const i32 = &a[1];
|
||||
/// let ptr2: *const i32 = &a[3];
|
||||
|
|
@ -767,8 +764,8 @@ impl<T: ?Sized> *const T {
|
|||
/// // This would be incorrect, as the pointers are not correctly ordered:
|
||||
/// // ptr1.sub_ptr(ptr2)
|
||||
/// ```
|
||||
#[unstable(feature = "ptr_sub_ptr", issue = "95892")]
|
||||
#[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")]
|
||||
#[stable(feature = "ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[inline]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
pub const unsafe fn sub_ptr(self, origin: *const T) -> usize
|
||||
|
|
@ -812,8 +809,8 @@ impl<T: ?Sized> *const T {
|
|||
///
|
||||
/// For non-`Sized` pointees this operation considers only the data pointers,
|
||||
/// ignoring the metadata.
|
||||
#[unstable(feature = "ptr_sub_ptr", issue = "95892")]
|
||||
#[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")]
|
||||
#[stable(feature = "ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[inline]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
pub const unsafe fn byte_sub_ptr<U: ?Sized>(self, origin: *const U) -> usize {
|
||||
|
|
|
|||
|
|
@ -895,7 +895,6 @@ impl<T: ?Sized> *mut T {
|
|||
/// to [`sub`](#method.sub)). The following are all equivalent, assuming
|
||||
/// that their safety preconditions are met:
|
||||
/// ```rust
|
||||
/// # #![feature(ptr_sub_ptr)]
|
||||
/// # unsafe fn blah(ptr: *mut i32, origin: *mut i32, count: usize) -> bool { unsafe {
|
||||
/// ptr.sub_ptr(origin) == count
|
||||
/// # &&
|
||||
|
|
@ -924,8 +923,6 @@ impl<T: ?Sized> *mut T {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(ptr_sub_ptr)]
|
||||
///
|
||||
/// let mut a = [0; 5];
|
||||
/// let p: *mut i32 = a.as_mut_ptr();
|
||||
/// unsafe {
|
||||
|
|
@ -940,8 +937,8 @@ impl<T: ?Sized> *mut T {
|
|||
///
|
||||
/// // This would be incorrect, as the pointers are not correctly ordered:
|
||||
/// // ptr1.offset_from(ptr2)
|
||||
#[unstable(feature = "ptr_sub_ptr", issue = "95892")]
|
||||
#[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")]
|
||||
#[stable(feature = "ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[inline]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
pub const unsafe fn sub_ptr(self, origin: *const T) -> usize
|
||||
|
|
@ -962,8 +959,8 @@ impl<T: ?Sized> *mut T {
|
|||
///
|
||||
/// For non-`Sized` pointees this operation considers only the data pointers,
|
||||
/// ignoring the metadata.
|
||||
#[unstable(feature = "ptr_sub_ptr", issue = "95892")]
|
||||
#[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")]
|
||||
#[stable(feature = "ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[inline]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
pub const unsafe fn byte_sub_ptr<U: ?Sized>(self, origin: *mut U) -> usize {
|
||||
|
|
|
|||
|
|
@ -856,7 +856,6 @@ impl<T: ?Sized> NonNull<T> {
|
|||
/// to [`sub`](#method.sub)). The following are all equivalent, assuming
|
||||
/// that their safety preconditions are met:
|
||||
/// ```rust
|
||||
/// # #![feature(ptr_sub_ptr)]
|
||||
/// # unsafe fn blah(ptr: std::ptr::NonNull<u32>, origin: std::ptr::NonNull<u32>, count: usize) -> bool { unsafe {
|
||||
/// ptr.sub_ptr(origin) == count
|
||||
/// # &&
|
||||
|
|
@ -885,7 +884,6 @@ impl<T: ?Sized> NonNull<T> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(ptr_sub_ptr)]
|
||||
/// use std::ptr::NonNull;
|
||||
///
|
||||
/// let a = [0; 5];
|
||||
|
|
@ -903,8 +901,8 @@ impl<T: ?Sized> NonNull<T> {
|
|||
/// ```
|
||||
#[inline]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
#[unstable(feature = "ptr_sub_ptr", issue = "95892")]
|
||||
#[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")]
|
||||
#[stable(feature = "ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const unsafe fn sub_ptr(self, subtracted: NonNull<T>) -> usize
|
||||
where
|
||||
T: Sized,
|
||||
|
|
@ -925,8 +923,8 @@ impl<T: ?Sized> NonNull<T> {
|
|||
/// ignoring the metadata.
|
||||
#[inline(always)]
|
||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
||||
#[unstable(feature = "ptr_sub_ptr", issue = "95892")]
|
||||
#[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")]
|
||||
#[stable(feature = "ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "const_ptr_sub_ptr", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const unsafe fn byte_sub_ptr<U: ?Sized>(self, origin: NonNull<U>) -> usize {
|
||||
// SAFETY: the caller must uphold the safety contract for `byte_sub_ptr`.
|
||||
unsafe { self.as_ptr().byte_sub_ptr(origin.as_ptr()) }
|
||||
|
|
|
|||
|
|
@ -87,7 +87,6 @@
|
|||
#![feature(try_blocks)]
|
||||
#![feature(try_find)]
|
||||
#![feature(try_trait_v2)]
|
||||
#![feature(unsigned_is_multiple_of)]
|
||||
#![feature(unsize)]
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
#![feature(unwrap_infallible)]
|
||||
|
|
|
|||
|
|
@ -388,7 +388,7 @@ mod uefi_command_internal {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn start_image(&mut self) -> io::Result<r_efi::efi::Status> {
|
||||
pub(crate) fn start_image(&mut self) -> io::Result<r_efi::efi::Status> {
|
||||
self.update_st_crc32()?;
|
||||
|
||||
// Use our system table instead of the default one
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ pub(crate) mod system_time_internal {
|
|||
|
||||
// This algorithm is based on the one described in the post
|
||||
// https://blog.reverberate.org/2020/05/12/optimizing-date-algorithms.html
|
||||
pub const fn uefi_time_to_duration(t: r_efi::system::Time) -> Duration {
|
||||
pub(crate) const fn uefi_time_to_duration(t: r_efi::system::Time) -> Duration {
|
||||
assert!(t.month <= 12);
|
||||
assert!(t.month != 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
cargo-features = ["public-dependency"]
|
||||
|
||||
[package]
|
||||
name = "sysroot"
|
||||
version = "0.0.0"
|
||||
|
|
@ -5,10 +7,10 @@ edition = "2021"
|
|||
|
||||
# this is a dummy crate to ensure that all required crates appear in the sysroot
|
||||
[dependencies]
|
||||
proc_macro = { path = "../proc_macro" }
|
||||
proc_macro = { path = "../proc_macro", public = true }
|
||||
profiler_builtins = { path = "../profiler_builtins", optional = true }
|
||||
std = { path = "../std" }
|
||||
test = { path = "../test" }
|
||||
std = { path = "../std", public = true }
|
||||
test = { path = "../test", public = true }
|
||||
|
||||
# Forward features to the `std` crate as necessary
|
||||
[features]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
cargo-features = ["public-dependency"]
|
||||
|
||||
[package]
|
||||
name = "test"
|
||||
version = "0.0.0"
|
||||
|
|
@ -5,8 +7,8 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
getopts = { version = "0.2.21", features = ['rustc-dep-of-std'] }
|
||||
std = { path = "../std" }
|
||||
core = { path = "../core" }
|
||||
std = { path = "../std", public = true }
|
||||
core = { path = "../core", public = true }
|
||||
|
||||
[target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
|
||||
libc = { version = "0.2.150", default-features = false }
|
||||
|
|
|
|||
|
|
@ -288,7 +288,7 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
|
|||
| ItemKind::Use(_, _)
|
||||
| ItemKind::ExternCrate(_)
|
||||
| ItemKind::ForeignMod { .. }
|
||||
| ItemKind::GlobalAsm(_)
|
||||
| ItemKind::GlobalAsm { .. }
|
||||
// We already have "visit_mod" above so no need to check it here.
|
||||
| ItemKind::Mod(_) => {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -439,7 +439,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||
}
|
||||
// If we're inlining, skip private items.
|
||||
_ if self.inlining && !is_pub => {}
|
||||
hir::ItemKind::GlobalAsm(..) => {}
|
||||
hir::ItemKind::GlobalAsm { .. } => {}
|
||||
hir::ItemKind::Use(_, hir::UseKind::ListStem) => {}
|
||||
hir::ItemKind::Use(path, kind) => {
|
||||
for &res in &path.res {
|
||||
|
|
|
|||
|
|
@ -362,7 +362,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
|
|||
}
|
||||
} else if let ItemKind::ForeignMod { .. } = item.kind {
|
||||
continue;
|
||||
} else if let ItemKind::GlobalAsm(_) = item.kind {
|
||||
} else if let ItemKind::GlobalAsm { .. } = item.kind {
|
||||
continue;
|
||||
} else if let ItemKind::Use(path, use_kind) = item.kind {
|
||||
if path.segments.is_empty() {
|
||||
|
|
@ -467,7 +467,7 @@ fn convert_module_item_kind(value: &ItemKind<'_>) -> SourceItemOrderingModuleIte
|
|||
ItemKind::Macro(..) => Macro,
|
||||
ItemKind::Mod(..) => Mod,
|
||||
ItemKind::ForeignMod { .. } => ForeignMod,
|
||||
ItemKind::GlobalAsm(..) => GlobalAsm,
|
||||
ItemKind::GlobalAsm { .. } => GlobalAsm,
|
||||
ItemKind::TyAlias(..) => TyAlias,
|
||||
ItemKind::Enum(..) => Enum,
|
||||
ItemKind::Struct(..) => Struct,
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
|
|||
| hir::ItemKind::Union(..) => {},
|
||||
hir::ItemKind::ExternCrate(..)
|
||||
| hir::ItemKind::ForeignMod { .. }
|
||||
| hir::ItemKind::GlobalAsm(..)
|
||||
| hir::ItemKind::GlobalAsm { .. }
|
||||
| hir::ItemKind::Impl { .. }
|
||||
| hir::ItemKind::Use(..) => note_prev_span_then_ret!(self.prev_span, it.span),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
|
|||
| hir::ItemKind::Static(..)
|
||||
| hir::ItemKind::Struct(..)
|
||||
| hir::ItemKind::TraitAlias(..)
|
||||
| hir::ItemKind::GlobalAsm(..)
|
||||
| hir::ItemKind::GlobalAsm { .. }
|
||||
| hir::ItemKind::TyAlias(..)
|
||||
| hir::ItemKind::Union(..)
|
||||
| hir::ItemKind::ExternCrate(..)
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ impl Context {
|
|||
}
|
||||
self.const_span = Some(body_span);
|
||||
},
|
||||
hir::BodyOwnerKind::Fn | hir::BodyOwnerKind::Closure => (),
|
||||
hir::BodyOwnerKind::Fn | hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::GlobalAsm => (),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -968,7 +968,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
|
|||
self.hash_expr(out_expr);
|
||||
}
|
||||
},
|
||||
InlineAsmOperand::Const { anon_const } | InlineAsmOperand::SymFn { anon_const } => {
|
||||
InlineAsmOperand::SymFn { expr } => {
|
||||
self.hash_expr(expr);
|
||||
}
|
||||
InlineAsmOperand::Const { anon_const } => {
|
||||
self.hash_body(anon_const.body);
|
||||
},
|
||||
InlineAsmOperand::SymStatic { path, def_id: _ } => self.hash_qpath(path),
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
#![feature(unqualified_local_imports)]
|
||||
#![feature(derive_coerce_pointee)]
|
||||
#![feature(arbitrary_self_types)]
|
||||
#![feature(unsigned_is_multiple_of)]
|
||||
#![feature(extract_if)]
|
||||
// Configure clippy and other lints
|
||||
#![allow(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
//@normalize-stderr-test: "\d+ < \d+" -> "$$ADDR < $$ADDR"
|
||||
#![feature(ptr_sub_ptr)]
|
||||
|
||||
fn main() {
|
||||
let arr = [0u8; 8];
|
||||
let ptr1 = arr.as_ptr();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
//@compile-flags: -Zmiri-permissive-provenance
|
||||
#![feature(ptr_sub_ptr)]
|
||||
use std::{mem, ptr};
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ fn layout_of_simd_ty(
|
|||
.size
|
||||
.checked_mul(e_len, dl)
|
||||
.ok_or(LayoutError::BadCalc(LayoutCalculatorError::SizeOverflow))?;
|
||||
let align = dl.vector_align(size);
|
||||
let align = dl.llvmlike_vector_align(size);
|
||||
let size = size.align_to(align.abi);
|
||||
|
||||
// Compute the placement of the vector fields:
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
//@ known-bug: #111709
|
||||
//@ edition: 2021
|
||||
|
||||
use core::arch::asm;
|
||||
|
||||
extern "C" fn test<T>() {}
|
||||
|
||||
fn uwu() {
|
||||
unsafe {
|
||||
asm!(
|
||||
"/* {0} */",
|
||||
sym test::<&mut ()>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
//@ known-bug: #111709
|
||||
//@ edition:2021
|
||||
|
||||
use core::arch::asm;
|
||||
|
||||
struct TrapFrame;
|
||||
|
||||
unsafe extern "C" fn _rust_abi_shim1<A, R>(arg: A, f: fn(A) -> R) -> R {
|
||||
f(arg)
|
||||
}
|
||||
|
||||
unsafe extern "C" fn _start_trap() {
|
||||
extern "Rust" {
|
||||
fn interrupt(tf: &mut TrapFrame);
|
||||
}
|
||||
asm!(
|
||||
"
|
||||
la a1, {irq}
|
||||
call {shim}
|
||||
",
|
||||
shim = sym crate::_rust_abi_shim1::<&mut TrapFrame, ()>,
|
||||
irq = sym interrupt,
|
||||
options(noreturn)
|
||||
)
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
//@ known-bug: #96304
|
||||
|
||||
#![feature(asm_sym)]
|
||||
core::arch::global_asm!("/* {} */", sym<&'static ()>::clone);
|
||||
|
||||
pub fn main() {}
|
||||
11
tests/ui/asm/asm-with-nested-closure.rs
Normal file
11
tests/ui/asm/asm-with-nested-closure.rs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
//@ build-pass
|
||||
//@ needs-asm-support
|
||||
|
||||
fn foo<const N: usize>() {}
|
||||
|
||||
core::arch::global_asm!("/* {} */", sym foo::<{
|
||||
|| {};
|
||||
0
|
||||
}>);
|
||||
|
||||
fn main() {}
|
||||
8
tests/ui/asm/global-asm-with-lifetimes.rs
Normal file
8
tests/ui/asm/global-asm-with-lifetimes.rs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
//@ build-pass
|
||||
//@ needs-asm-support
|
||||
|
||||
fn foo<T>() {}
|
||||
|
||||
core::arch::global_asm!("/* {} */", sym foo::<&'static ()>);
|
||||
|
||||
fn main() {}
|
||||
17
tests/ui/asm/inline-asm-with-lifetimes.bad.stderr
Normal file
17
tests/ui/asm/inline-asm-with-lifetimes.bad.stderr
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
error[E0309]: the parameter type `T` may not live long enough
|
||||
--> $DIR/inline-asm-with-lifetimes.rs:17:26
|
||||
|
|
||||
LL | fn test<'a: 'a, T>() {
|
||||
| -- the parameter type `T` must be valid for the lifetime `'a` as defined here...
|
||||
LL | unsafe {
|
||||
LL | asm!("/* {} */", sym dep::<'a, T> );
|
||||
| ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
||||
|
|
||||
help: consider adding an explicit lifetime bound
|
||||
|
|
||||
LL | fn test<'a: 'a, T: 'a>() {
|
||||
| ++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0309`.
|
||||
22
tests/ui/asm/inline-asm-with-lifetimes.rs
Normal file
22
tests/ui/asm/inline-asm-with-lifetimes.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
//@ revisions: good bad
|
||||
//@[good] build-pass
|
||||
//@ needs-asm-support
|
||||
|
||||
use std::arch::asm;
|
||||
|
||||
// lifetime requirement, we should check it!!
|
||||
#[cfg(bad)]
|
||||
fn dep<'a, T: 'a>() {}
|
||||
|
||||
// no lifetime requirement
|
||||
#[cfg(good)]
|
||||
fn dep<'a: 'a, T>() {}
|
||||
|
||||
fn test<'a: 'a, T>() {
|
||||
unsafe {
|
||||
asm!("/* {} */", sym dep::<'a, T> );
|
||||
//[bad]~^ ERROR the parameter type `T` may not live long enough
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,8 +1,5 @@
|
|||
//@ run-pass
|
||||
|
||||
#![feature(const_ptr_sub_ptr)]
|
||||
#![feature(ptr_sub_ptr)]
|
||||
|
||||
struct Struct {
|
||||
field: (),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
//@ normalize-stderr: "\d+ bytes" -> "$$BYTES bytes"
|
||||
#![feature(const_ptr_sub_ptr)]
|
||||
#![feature(core_intrinsics)]
|
||||
|
||||
use std::intrinsics::{ptr_offset_from, ptr_offset_from_unsigned};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/offset_from_ub.rs:19:27
|
||||
--> $DIR/offset_from_ub.rs:18:27
|
||||
|
|
||||
LL | let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on two different pointers that are not both derived from the same allocation
|
||||
|
|
@ -12,67 +12,67 @@ error[E0080]: evaluation of constant value failed
|
|||
note: inside `std::ptr::const_ptr::<impl *const u8>::offset_from`
|
||||
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||
note: inside `NOT_PTR`
|
||||
--> $DIR/offset_from_ub.rs:25:14
|
||||
--> $DIR/offset_from_ub.rs:24:14
|
||||
|
|
||||
LL | unsafe { (42 as *const u8).offset_from(&5u8) as usize }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/offset_from_ub.rs:32:14
|
||||
--> $DIR/offset_from_ub.rs:31:14
|
||||
|
|
||||
LL | unsafe { ptr_offset_from(field_ptr, base_ptr as *const u16) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ exact_div: 1_isize cannot be divided by 2_isize without remainder
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/offset_from_ub.rs:39:14
|
||||
--> $DIR/offset_from_ub.rs:38:14
|
||||
|
|
||||
LL | unsafe { ptr_offset_from(ptr2, ptr1) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on two different pointers that are not both derived from the same allocation
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/offset_from_ub.rs:48:14
|
||||
--> $DIR/offset_from_ub.rs:47:14
|
||||
|
|
||||
LL | unsafe { ptr_offset_from(end_ptr, start_ptr) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on two different pointers where the memory range between them is not in-bounds of an allocation
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/offset_from_ub.rs:57:14
|
||||
--> $DIR/offset_from_ub.rs:56:14
|
||||
|
|
||||
LL | unsafe { ptr_offset_from(start_ptr, end_ptr) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on two different pointers where the memory range between them is not in-bounds of an allocation
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/offset_from_ub.rs:66:14
|
||||
--> $DIR/offset_from_ub.rs:65:14
|
||||
|
|
||||
LL | unsafe { ptr_offset_from_unsigned(field_ptr, base_ptr) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called on two different pointers that are not both derived from the same allocation
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/offset_from_ub.rs:73:14
|
||||
--> $DIR/offset_from_ub.rs:72:14
|
||||
|
|
||||
LL | unsafe { ptr_offset_from(ptr2, ptr1) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called when first pointer is too far ahead of second
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/offset_from_ub.rs:79:14
|
||||
--> $DIR/offset_from_ub.rs:78:14
|
||||
|
|
||||
LL | unsafe { ptr_offset_from(ptr1, ptr2) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called when first pointer is too far before second
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/offset_from_ub.rs:87:14
|
||||
--> $DIR/offset_from_ub.rs:86:14
|
||||
|
|
||||
LL | unsafe { ptr_offset_from(ptr1, ptr2) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called when first pointer is too far before second
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/offset_from_ub.rs:94:14
|
||||
--> $DIR/offset_from_ub.rs:93:14
|
||||
|
|
||||
LL | unsafe { ptr_offset_from_unsigned(p, p.add(2) ) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called when first pointer has smaller offset than second: 0 < 8
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/offset_from_ub.rs:101:14
|
||||
--> $DIR/offset_from_ub.rs:100:14
|
||||
|
|
||||
LL | unsafe { ptr_offset_from_unsigned(ptr2, ptr1) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called when first pointer is too far ahead of second
|
||||
|
|
@ -85,7 +85,7 @@ error[E0080]: evaluation of constant value failed
|
|||
note: inside `std::ptr::const_ptr::<impl *const u8>::offset_from`
|
||||
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||
note: inside `OFFSET_VERY_FAR1`
|
||||
--> $DIR/offset_from_ub.rs:110:14
|
||||
--> $DIR/offset_from_ub.rs:109:14
|
||||
|
|
||||
LL | unsafe { ptr2.offset_from(ptr1) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -98,7 +98,7 @@ error[E0080]: evaluation of constant value failed
|
|||
note: inside `std::ptr::const_ptr::<impl *const u8>::offset_from`
|
||||
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
||||
note: inside `OFFSET_VERY_FAR2`
|
||||
--> $DIR/offset_from_ub.rs:116:14
|
||||
--> $DIR/offset_from_ub.rs:115:14
|
||||
|
|
||||
LL | unsafe { ptr1.offset_from(ptr2.wrapping_offset(1)) }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
|||
|
|
@ -7,11 +7,5 @@ error: unwinding panics are not supported without std
|
|||
= help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding
|
||||
= note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem
|
||||
|
||||
error: requires `sized` lang_item
|
||||
--> $DIR/empty-extern-arg.rs:6:11
|
||||
|
|
||||
LL | fn main() {}
|
||||
| ^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
//@ aux-crate:priv:reexport=reexport.rs
|
||||
//@ compile-flags: -Zunstable-options
|
||||
//@ check-pass
|
||||
|
||||
// Checks the behavior of a reexported item from a private dependency.
|
||||
|
||||
|
|
@ -9,7 +8,7 @@
|
|||
|
||||
extern crate reexport;
|
||||
|
||||
// FIXME: This should trigger.
|
||||
pub fn leaks_priv() -> reexport::Shared {
|
||||
//~^ ERROR type `Shared` from private dependency 'shared' in public interface
|
||||
reexport::Shared
|
||||
}
|
||||
|
|
|
|||
14
tests/ui/privacy/pub-priv-dep/reexport_from_priv.stderr
Normal file
14
tests/ui/privacy/pub-priv-dep/reexport_from_priv.stderr
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
error: type `Shared` from private dependency 'shared' in public interface
|
||||
--> $DIR/reexport_from_priv.rs:11:1
|
||||
|
|
||||
LL | pub fn leaks_priv() -> reexport::Shared {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/reexport_from_priv.rs:7:9
|
||||
|
|
||||
LL | #![deny(exported_private_dependencies)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
//@ aux-crate:priv:shared=shared.rs
|
||||
//@ aux-crate:priv:indirect1=indirect1.rs
|
||||
//@ compile-flags: -Zunstable-options
|
||||
//@ check-pass
|
||||
|
||||
// A shared dependency, where it is only indirectly public.
|
||||
//
|
||||
|
|
@ -23,7 +22,7 @@
|
|||
extern crate shared;
|
||||
extern crate indirect1;
|
||||
|
||||
// FIXME: This should trigger.
|
||||
pub fn leaks_priv() -> shared::Shared {
|
||||
//~^ ERROR type `Shared` from private dependency 'shared' in public interface
|
||||
shared::Shared
|
||||
}
|
||||
|
|
|
|||
14
tests/ui/privacy/pub-priv-dep/shared_indirect.stderr
Normal file
14
tests/ui/privacy/pub-priv-dep/shared_indirect.stderr
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
error: type `Shared` from private dependency 'shared' in public interface
|
||||
--> $DIR/shared_indirect.rs:25:1
|
||||
|
|
||||
LL | pub fn leaks_priv() -> shared::Shared {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/shared_indirect.rs:20:9
|
||||
|
|
||||
LL | #![deny(exported_private_dependencies)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
19
tests/ui/proc-macro/auxiliary/quote-issue-137345.rs
Normal file
19
tests/ui/proc-macro/auxiliary/quote-issue-137345.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
extern crate proc_macro;
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
fn items() -> impl IntoIterator<Item = i32> {
|
||||
vec![1, 2, 3]
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! quote {
|
||||
// Rule for any other number of tokens.
|
||||
($($tt:tt)*) => {{
|
||||
fn items() -> impl IntoIterator<Item = i32> {
|
||||
vec![1, 2, 3]
|
||||
}
|
||||
let _s = TokenStream::new();
|
||||
let other_items = items().map(|i| i + 1);
|
||||
_s
|
||||
}};
|
||||
}
|
||||
|
|
@ -3,7 +3,8 @@
|
|||
|
||||
//@ edition:2018
|
||||
//@ proc-macro: issue-59191.rs
|
||||
//@ error-pattern: requires `sized` lang_item
|
||||
//@ needs-unwind (affects error output)
|
||||
//@ error-pattern: error: `#[panic_handler]` function required
|
||||
|
||||
#![feature(custom_inner_attributes)]
|
||||
#![issue_59191::no_main]
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
error: requires `sized` lang_item
|
||||
--> $DIR/issue-59191-replace-root-with-fn.rs:9:1
|
||||
|
|
||||
LL | #![issue_59191::no_main]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this error originates in the attribute macro `issue_59191::no_main` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
error: `#[panic_handler]` function required, but not found
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error: unwinding panics are not supported without std
|
||||
|
|
||||
= help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding
|
||||
= note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ Respanned: TokenStream [Ident { ident: "$crate", span: $DIR/auxiliary/make-macro
|
|||
use core /* 0#1 */::prelude /* 0#1 */::rust_2018 /* 0#1 */::*;
|
||||
#[macro_use /* 0#1 */]
|
||||
extern crate core /* 0#1 */;
|
||||
extern crate compiler_builtins /* NNN */ as _ /* 0#1 */;
|
||||
// Don't load unnecessary hygiene information from std
|
||||
extern crate std /* 0#0 */;
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
|
|||
use ::core /* 0#1 */::prelude /* 0#1 */::rust_2015 /* 0#1 */::*;
|
||||
#[macro_use /* 0#1 */]
|
||||
extern crate core /* 0#2 */;
|
||||
extern crate compiler_builtins /* NNN */ as _ /* 0#2 */;
|
||||
// Don't load unnecessary hygiene information from std
|
||||
extern crate std /* 0#0 */;
|
||||
|
||||
|
|
|
|||
17
tests/ui/proc-macro/valid-sugg-issue-137345.rs
Normal file
17
tests/ui/proc-macro/valid-sugg-issue-137345.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
//@ aux-crate: quote=quote-issue-137345.rs
|
||||
|
||||
extern crate proc_macro;
|
||||
extern crate quote;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
pub fn default_args_fn(_: TokenStream) -> TokenStream {
|
||||
let decl_macro = TokenStream::new();
|
||||
|
||||
quote::quote! {
|
||||
#(#decl_macro)*
|
||||
}
|
||||
.into() //~^^^ ERROR no method named `map` found for opaque type
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
13
tests/ui/proc-macro/valid-sugg-issue-137345.stderr
Normal file
13
tests/ui/proc-macro/valid-sugg-issue-137345.stderr
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
error[E0599]: no method named `map` found for opaque type `impl IntoIterator<Item = i32>` in the current scope
|
||||
--> $DIR/valid-sugg-issue-137345.rs:11:5
|
||||
|
|
||||
LL | / quote::quote! {
|
||||
LL | | #(#decl_macro)*
|
||||
LL | | }
|
||||
| |_____^ `impl IntoIterator<Item = i32>` is not an iterator
|
||||
|
|
||||
= note: this error originates in the macro `quote::quote` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0599`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue