Auto merge of #131237 - GuillaumeGomez:rollup-il2i7z7, r=GuillaumeGomez
Rollup of 4 pull requests Successful merges: - #131034 (Implement RFC3695 Allow boolean literals as cfg predicates) - #131202 (Use wide pointers consistenly across the compiler) - #131230 (Enable `--no-sandbox` option by default for rustdoc GUI tests) - #131232 (Week off of reviews to focus on docs) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
c39f318c5e
71 changed files with 407 additions and 211 deletions
|
@ -527,6 +527,16 @@ impl NestedMetaItem {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem` or if it's
|
||||
/// `NestedMetaItem::Lit(MetaItemLit { kind: LitKind::Bool(_), .. })`.
|
||||
pub fn meta_item_or_bool(&self) -> Option<&NestedMetaItem> {
|
||||
match self {
|
||||
NestedMetaItem::MetaItem(_item) => Some(self),
|
||||
NestedMetaItem::Lit(MetaItemLit { kind: LitKind::Bool(_), .. }) => Some(self),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem`.
|
||||
pub fn meta_item(&self) -> Option<&MetaItem> {
|
||||
match self {
|
||||
|
|
|
@ -107,6 +107,8 @@ attr_unknown_version_literal =
|
|||
attr_unstable_cfg_target_compact =
|
||||
compact `cfg(target(..))` is experimental and subject to change
|
||||
|
||||
attr_unsupported_literal_cfg_boolean =
|
||||
literal in `cfg` predicate value must be a boolean
|
||||
attr_unsupported_literal_cfg_string =
|
||||
literal in `cfg` predicate value must be a string
|
||||
attr_unsupported_literal_deprecated_kv_pair =
|
||||
|
|
|
@ -18,7 +18,7 @@ use rustc_session::parse::feature_err;
|
|||
use rustc_session::{RustcVersion, Session};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::hygiene::Transparency;
|
||||
use rustc_span::symbol::{Symbol, sym};
|
||||
use rustc_span::symbol::{Symbol, kw, sym};
|
||||
|
||||
use crate::fluent_generated;
|
||||
use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
|
||||
|
@ -36,6 +36,7 @@ pub fn is_builtin_attr(attr: &Attribute) -> bool {
|
|||
pub(crate) enum UnsupportedLiteralReason {
|
||||
Generic,
|
||||
CfgString,
|
||||
CfgBoolean,
|
||||
DeprecatedString,
|
||||
DeprecatedKvPair,
|
||||
}
|
||||
|
@ -533,7 +534,7 @@ pub struct Condition {
|
|||
|
||||
/// Tests if a cfg-pattern matches the cfg set
|
||||
pub fn cfg_matches(
|
||||
cfg: &ast::MetaItem,
|
||||
cfg: &ast::NestedMetaItem,
|
||||
sess: &Session,
|
||||
lint_node_id: NodeId,
|
||||
features: Option<&Features>,
|
||||
|
@ -604,12 +605,43 @@ pub fn parse_version(s: Symbol) -> Option<RustcVersion> {
|
|||
/// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to
|
||||
/// evaluate individual items.
|
||||
pub fn eval_condition(
|
||||
cfg: &ast::MetaItem,
|
||||
cfg: &ast::NestedMetaItem,
|
||||
sess: &Session,
|
||||
features: Option<&Features>,
|
||||
eval: &mut impl FnMut(Condition) -> bool,
|
||||
) -> bool {
|
||||
let dcx = sess.dcx();
|
||||
|
||||
let cfg = match cfg {
|
||||
ast::NestedMetaItem::MetaItem(meta_item) => meta_item,
|
||||
ast::NestedMetaItem::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => {
|
||||
if let Some(features) = features {
|
||||
// we can't use `try_gate_cfg` as symbols don't differentiate between `r#true`
|
||||
// and `true`, and we want to keep the former working without feature gate
|
||||
gate_cfg(
|
||||
&((
|
||||
if *b { kw::True } else { kw::False },
|
||||
sym::cfg_boolean_literals,
|
||||
|features: &Features| features.cfg_boolean_literals,
|
||||
)),
|
||||
cfg.span(),
|
||||
sess,
|
||||
features,
|
||||
);
|
||||
}
|
||||
return *b;
|
||||
}
|
||||
_ => {
|
||||
dcx.emit_err(session_diagnostics::UnsupportedLiteral {
|
||||
span: cfg.span(),
|
||||
reason: UnsupportedLiteralReason::CfgBoolean,
|
||||
is_bytestr: false,
|
||||
start_point_span: sess.source_map().start_point(cfg.span()),
|
||||
});
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
match &cfg.kind {
|
||||
ast::MetaItemKind::List(mis) if cfg.name_or_empty() == sym::version => {
|
||||
try_gate_cfg(sym::version, cfg.span, sess, features);
|
||||
|
@ -645,7 +677,7 @@ pub fn eval_condition(
|
|||
}
|
||||
ast::MetaItemKind::List(mis) => {
|
||||
for mi in mis.iter() {
|
||||
if !mi.is_meta_item() {
|
||||
if mi.meta_item_or_bool().is_none() {
|
||||
dcx.emit_err(session_diagnostics::UnsupportedLiteral {
|
||||
span: mi.span(),
|
||||
reason: UnsupportedLiteralReason::Generic,
|
||||
|
@ -663,23 +695,19 @@ pub fn eval_condition(
|
|||
.iter()
|
||||
// We don't use any() here, because we want to evaluate all cfg condition
|
||||
// as eval_condition can (and does) extra checks
|
||||
.fold(false, |res, mi| {
|
||||
res | eval_condition(mi.meta_item().unwrap(), sess, features, eval)
|
||||
}),
|
||||
.fold(false, |res, mi| res | eval_condition(mi, sess, features, eval)),
|
||||
sym::all => mis
|
||||
.iter()
|
||||
// We don't use all() here, because we want to evaluate all cfg condition
|
||||
// as eval_condition can (and does) extra checks
|
||||
.fold(true, |res, mi| {
|
||||
res & eval_condition(mi.meta_item().unwrap(), sess, features, eval)
|
||||
}),
|
||||
.fold(true, |res, mi| res & eval_condition(mi, sess, features, eval)),
|
||||
sym::not => {
|
||||
let [mi] = mis.as_slice() else {
|
||||
dcx.emit_err(session_diagnostics::ExpectedOneCfgPattern { span: cfg.span });
|
||||
return false;
|
||||
};
|
||||
|
||||
!eval_condition(mi.meta_item().unwrap(), sess, features, eval)
|
||||
!eval_condition(mi, sess, features, eval)
|
||||
}
|
||||
sym::target => {
|
||||
if let Some(features) = features
|
||||
|
@ -700,7 +728,12 @@ pub fn eval_condition(
|
|||
seg.ident.name = Symbol::intern(&format!("target_{}", seg.ident.name));
|
||||
}
|
||||
|
||||
res & eval_condition(&mi, sess, features, eval)
|
||||
res & eval_condition(
|
||||
&ast::NestedMetaItem::MetaItem(mi),
|
||||
sess,
|
||||
features,
|
||||
eval,
|
||||
)
|
||||
})
|
||||
}
|
||||
_ => {
|
||||
|
|
|
@ -206,6 +206,7 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for UnsupportedLiteral {
|
|||
let mut diag = Diag::new(dcx, level, match self.reason {
|
||||
UnsupportedLiteralReason::Generic => fluent::attr_unsupported_literal_generic,
|
||||
UnsupportedLiteralReason::CfgString => fluent::attr_unsupported_literal_cfg_string,
|
||||
UnsupportedLiteralReason::CfgBoolean => fluent::attr_unsupported_literal_cfg_boolean,
|
||||
UnsupportedLiteralReason::DeprecatedString => {
|
||||
fluent::attr_unsupported_literal_deprecated_string
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ use rustc_ast::token;
|
|||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_errors::PResult;
|
||||
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
|
||||
use rustc_parse::parser::attr::AllowLeadingUnsafe;
|
||||
use rustc_span::Span;
|
||||
use {rustc_ast as ast, rustc_attr as attr};
|
||||
|
||||
|
@ -36,14 +35,18 @@ pub(crate) fn expand_cfg(
|
|||
})
|
||||
}
|
||||
|
||||
fn parse_cfg<'a>(cx: &ExtCtxt<'a>, span: Span, tts: TokenStream) -> PResult<'a, ast::MetaItem> {
|
||||
fn parse_cfg<'a>(
|
||||
cx: &ExtCtxt<'a>,
|
||||
span: Span,
|
||||
tts: TokenStream,
|
||||
) -> PResult<'a, ast::NestedMetaItem> {
|
||||
let mut p = cx.new_parser_from_tts(tts);
|
||||
|
||||
if p.token == token::Eof {
|
||||
return Err(cx.dcx().create_err(errors::RequiresCfgPattern { span }));
|
||||
}
|
||||
|
||||
let cfg = p.parse_meta_item(AllowLeadingUnsafe::No)?;
|
||||
let cfg = p.parse_meta_item_inner()?;
|
||||
|
||||
let _ = p.eat(&token::Comma);
|
||||
|
||||
|
|
|
@ -168,7 +168,7 @@ fn main() {
|
|||
|
||||
foo(I64X2([0, 0]));
|
||||
|
||||
transmute_fat_pointer();
|
||||
transmute_wide_pointer();
|
||||
|
||||
rust_call_abi();
|
||||
|
||||
|
@ -192,7 +192,7 @@ type TwoPtrs = i64;
|
|||
#[cfg(target_pointer_width = "64")]
|
||||
type TwoPtrs = i128;
|
||||
|
||||
fn transmute_fat_pointer() -> TwoPtrs {
|
||||
fn transmute_wide_pointer() -> TwoPtrs {
|
||||
unsafe { transmute::<_, TwoPtrs>("true !") }
|
||||
}
|
||||
|
||||
|
|
|
@ -713,17 +713,17 @@ fn codegen_stmt<'tcx>(
|
|||
let from_ty = operand.layout().ty;
|
||||
let to_ty = fx.monomorphize(to_ty);
|
||||
|
||||
fn is_fat_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
fn is_wide_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
ty.builtin_deref(true)
|
||||
.is_some_and(|pointee_ty| has_ptr_meta(fx.tcx, pointee_ty))
|
||||
}
|
||||
|
||||
if is_fat_ptr(fx, from_ty) {
|
||||
if is_fat_ptr(fx, to_ty) {
|
||||
// fat-ptr -> fat-ptr
|
||||
if is_wide_ptr(fx, from_ty) {
|
||||
if is_wide_ptr(fx, to_ty) {
|
||||
// wide-ptr -> wide-ptr
|
||||
lval.write_cvalue(fx, operand.cast_pointer_to(dest_layout));
|
||||
} else {
|
||||
// fat-ptr -> thin-ptr
|
||||
// wide-ptr -> thin-ptr
|
||||
let (ptr, _extra) = operand.load_scalar_pair(fx);
|
||||
lval.write_cvalue(fx, CValue::by_val(ptr, dest_layout))
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ fn clif_pair_type_from_ty<'tcx>(
|
|||
})
|
||||
}
|
||||
|
||||
/// Is a pointer to this type a fat ptr?
|
||||
/// Is a pointer to this type a wide ptr?
|
||||
pub(crate) fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
if ty.is_sized(tcx, ParamEnv::reveal_all()) {
|
||||
return false;
|
||||
|
|
|
@ -139,7 +139,7 @@ impl DebugContext {
|
|||
|
||||
pointer_type_id
|
||||
} else {
|
||||
// FIXME implement debuginfo for fat pointers
|
||||
// FIXME implement debuginfo for wide pointers
|
||||
self.placeholder_for_type(tcx, type_dbg, ptr_type)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -478,7 +478,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
|
||||
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
||||
});
|
||||
require!(metadata.is_unit(), InvalidMonomorphization::CastFatPointer {
|
||||
require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
|
||||
span,
|
||||
name,
|
||||
ty: in_elem
|
||||
|
@ -493,7 +493,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
|
||||
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
||||
});
|
||||
require!(metadata.is_unit(), InvalidMonomorphization::CastFatPointer {
|
||||
require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
|
||||
span,
|
||||
name,
|
||||
ty: out_elem
|
||||
|
|
|
@ -207,7 +207,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
|
|||
// layout.
|
||||
if let Abi::Scalar(ref scalar) = self.abi {
|
||||
// Use a different cache for scalars because pointers to DSTs
|
||||
// can be either fat or thin (data pointers of fat pointers).
|
||||
// can be either wide or thin (data pointers of wide pointers).
|
||||
if let Some(&ty) = cx.scalar_types.borrow().get(&self.ty) {
|
||||
return ty;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue};
|
|||
use rustc_codegen_ssa::traits::*;
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
pub(crate) use rustc_middle::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
|
||||
pub(crate) use rustc_middle::ty::layout::{WIDE_PTR_ADDR, WIDE_PTR_EXTRA};
|
||||
use rustc_middle::{bug, ty};
|
||||
use rustc_session::config;
|
||||
pub(crate) use rustc_target::abi::call::*;
|
||||
|
|
|
@ -34,7 +34,7 @@ use super::utils::{
|
|||
};
|
||||
use crate::common::CodegenCx;
|
||||
use crate::debuginfo::metadata::type_map::build_type_with_children;
|
||||
use crate::debuginfo::utils::{FatPtrKind, fat_pointer_kind};
|
||||
use crate::debuginfo::utils::{WidePtrKind, wide_pointer_kind};
|
||||
use crate::llvm::debuginfo::{
|
||||
DIDescriptor, DIFile, DIFlags, DILexicalBlock, DIScope, DIType, DebugEmissionKind,
|
||||
DebugNameTableKind,
|
||||
|
@ -161,7 +161,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
|||
unique_type_id: UniqueTypeId<'tcx>,
|
||||
) -> DINodeCreationResult<'ll> {
|
||||
// The debuginfo generated by this function is only valid if `ptr_type` is really just
|
||||
// a (fat) pointer. Make sure it is not called for e.g. `Box<T, NonZSTAllocator>`.
|
||||
// a (wide) pointer. Make sure it is not called for e.g. `Box<T, NonZSTAllocator>`.
|
||||
assert_eq!(
|
||||
cx.size_and_align_of(ptr_type),
|
||||
cx.size_and_align_of(Ty::new_mut_ptr(cx.tcx, pointee_type))
|
||||
|
@ -174,7 +174,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
|||
let data_layout = &cx.tcx.data_layout;
|
||||
let ptr_type_debuginfo_name = compute_debuginfo_type_name(cx.tcx, ptr_type, true);
|
||||
|
||||
match fat_pointer_kind(cx, pointee_type) {
|
||||
match wide_pointer_kind(cx, pointee_type) {
|
||||
None => {
|
||||
// This is a thin pointer. Create a regular pointer type and give it the correct name.
|
||||
assert_eq!(
|
||||
|
@ -197,7 +197,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
|||
|
||||
DINodeCreationResult { di_node, already_stored_in_typemap: false }
|
||||
}
|
||||
Some(fat_pointer_kind) => {
|
||||
Some(wide_pointer_kind) => {
|
||||
type_map::build_type_with_children(
|
||||
cx,
|
||||
type_map::stub(
|
||||
|
@ -210,7 +210,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
|||
DIFlags::FlagZero,
|
||||
),
|
||||
|cx, owner| {
|
||||
// FIXME: If this fat pointer is a `Box` then we don't want to use its
|
||||
// FIXME: If this wide pointer is a `Box` then we don't want to use its
|
||||
// type layout and instead use the layout of the raw pointer inside
|
||||
// of it.
|
||||
// The proper way to handle this is to not treat Box as a pointer
|
||||
|
@ -227,16 +227,16 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
|||
};
|
||||
|
||||
let layout = cx.layout_of(layout_type);
|
||||
let addr_field = layout.field(cx, abi::FAT_PTR_ADDR);
|
||||
let extra_field = layout.field(cx, abi::FAT_PTR_EXTRA);
|
||||
let addr_field = layout.field(cx, abi::WIDE_PTR_ADDR);
|
||||
let extra_field = layout.field(cx, abi::WIDE_PTR_EXTRA);
|
||||
|
||||
let (addr_field_name, extra_field_name) = match fat_pointer_kind {
|
||||
FatPtrKind::Dyn => ("pointer", "vtable"),
|
||||
FatPtrKind::Slice => ("data_ptr", "length"),
|
||||
let (addr_field_name, extra_field_name) = match wide_pointer_kind {
|
||||
WidePtrKind::Dyn => ("pointer", "vtable"),
|
||||
WidePtrKind::Slice => ("data_ptr", "length"),
|
||||
};
|
||||
|
||||
assert_eq!(abi::FAT_PTR_ADDR, 0);
|
||||
assert_eq!(abi::FAT_PTR_EXTRA, 1);
|
||||
assert_eq!(abi::WIDE_PTR_ADDR, 0);
|
||||
assert_eq!(abi::WIDE_PTR_EXTRA, 1);
|
||||
|
||||
// The data pointer type is a regular, thin pointer, regardless of whether this
|
||||
// is a slice or a trait object.
|
||||
|
@ -258,7 +258,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
|||
owner,
|
||||
addr_field_name,
|
||||
(addr_field.size, addr_field.align.abi),
|
||||
layout.fields.offset(abi::FAT_PTR_ADDR),
|
||||
layout.fields.offset(abi::WIDE_PTR_ADDR),
|
||||
DIFlags::FlagZero,
|
||||
data_ptr_type_di_node,
|
||||
),
|
||||
|
@ -267,7 +267,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
|||
owner,
|
||||
extra_field_name,
|
||||
(extra_field.size, extra_field.align.abi),
|
||||
layout.fields.offset(abi::FAT_PTR_EXTRA),
|
||||
layout.fields.offset(abi::WIDE_PTR_EXTRA),
|
||||
DIFlags::FlagZero,
|
||||
type_di_node(cx, extra_field.ty),
|
||||
),
|
||||
|
@ -391,7 +391,7 @@ fn build_dyn_type_di_node<'ll, 'tcx>(
|
|||
///
|
||||
/// NOTE: We currently emit just emit the debuginfo for the element type here
|
||||
/// (i.e. `T` for slices and `u8` for `str`), so that we end up with
|
||||
/// `*const T` for the `data_ptr` field of the corresponding fat-pointer
|
||||
/// `*const T` for the `data_ptr` field of the corresponding wide-pointer
|
||||
/// debuginfo of `&[T]`.
|
||||
///
|
||||
/// It would be preferable and more accurate if we emitted a DIArray of T
|
||||
|
|
|
@ -49,23 +49,23 @@ pub(crate) fn get_namespace_for_item<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId
|
|||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub(crate) enum FatPtrKind {
|
||||
pub(crate) enum WidePtrKind {
|
||||
Slice,
|
||||
Dyn,
|
||||
}
|
||||
|
||||
/// Determines if `pointee_ty` is slice-like or trait-object-like, i.e.
|
||||
/// if the second field of the fat pointer is a length or a vtable-pointer.
|
||||
/// If `pointee_ty` does not require a fat pointer (because it is Sized) then
|
||||
/// if the second field of the wide pointer is a length or a vtable-pointer.
|
||||
/// If `pointee_ty` does not require a wide pointer (because it is Sized) then
|
||||
/// the function returns `None`.
|
||||
pub(crate) fn fat_pointer_kind<'ll, 'tcx>(
|
||||
pub(crate) fn wide_pointer_kind<'ll, 'tcx>(
|
||||
cx: &CodegenCx<'ll, 'tcx>,
|
||||
pointee_ty: Ty<'tcx>,
|
||||
) -> Option<FatPtrKind> {
|
||||
) -> Option<WidePtrKind> {
|
||||
let pointee_tail_ty = cx.tcx.struct_tail_for_codegen(pointee_ty, cx.param_env());
|
||||
let layout = cx.layout_of(pointee_tail_ty);
|
||||
trace!(
|
||||
"fat_pointer_kind: {:?} has layout {:?} (is_unsized? {})",
|
||||
"wide_pointer_kind: {:?} has layout {:?} (is_unsized? {})",
|
||||
pointee_tail_ty,
|
||||
layout,
|
||||
layout.is_unsized()
|
||||
|
@ -76,8 +76,8 @@ pub(crate) fn fat_pointer_kind<'ll, 'tcx>(
|
|||
}
|
||||
|
||||
match *pointee_tail_ty.kind() {
|
||||
ty::Str | ty::Slice(_) => Some(FatPtrKind::Slice),
|
||||
ty::Dynamic(..) => Some(FatPtrKind::Dyn),
|
||||
ty::Str | ty::Slice(_) => Some(WidePtrKind::Slice),
|
||||
ty::Dynamic(..) => Some(WidePtrKind::Dyn),
|
||||
ty::Foreign(_) => {
|
||||
// Assert that pointers to foreign types really are thin:
|
||||
assert_eq!(
|
||||
|
@ -90,7 +90,7 @@ pub(crate) fn fat_pointer_kind<'ll, 'tcx>(
|
|||
// For all other pointee types we should already have returned None
|
||||
// at the beginning of the function.
|
||||
panic!(
|
||||
"fat_pointer_kind() - Encountered unexpected `pointee_tail_ty`: {pointee_tail_ty:?}"
|
||||
"wide_pointer_kind() - Encountered unexpected `pointee_tail_ty`: {pointee_tail_ty:?}"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2185,7 +2185,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
|
||||
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
||||
});
|
||||
require!(metadata.is_unit(), InvalidMonomorphization::CastFatPointer {
|
||||
require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
|
||||
span,
|
||||
name,
|
||||
ty: in_elem
|
||||
|
@ -2200,7 +2200,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
|
||||
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
||||
});
|
||||
require!(metadata.is_unit(), InvalidMonomorphization::CastFatPointer {
|
||||
require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
|
||||
span,
|
||||
name,
|
||||
ty: out_elem
|
||||
|
|
|
@ -199,7 +199,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
|||
// layout.
|
||||
if let Abi::Scalar(scalar) = self.abi {
|
||||
// Use a different cache for scalars because pointers to DSTs
|
||||
// can be either fat or thin (data pointers of fat pointers).
|
||||
// can be either wide or thin (data pointers of wide pointers).
|
||||
if let Some(&llty) = cx.scalar_lltypes.borrow().get(&self.ty) {
|
||||
return llty;
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ codegen_ssa_invalid_monomorphization_basic_integer_type = invalid monomorphizati
|
|||
|
||||
codegen_ssa_invalid_monomorphization_cannot_return = invalid monomorphization of `{$name}` intrinsic: cannot return `{$ret_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_cast_fat_pointer = invalid monomorphization of `{$name}` intrinsic: cannot cast fat pointer `{$ty}`
|
||||
codegen_ssa_invalid_monomorphization_cast_wide_pointer = invalid monomorphization of `{$name}` intrinsic: cannot cast wide pointer `{$ty}`
|
||||
|
||||
codegen_ssa_invalid_monomorphization_expected_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of second argument `{$second_arg}` to be a pointer to the element type `{$in_elem}` of the first argument `{$in_ty}`, found `{$expected_element}` != `{$mutability} {$in_elem}`
|
||||
|
||||
|
|
|
@ -916,8 +916,8 @@ pub enum InvalidMonomorphization<'tcx> {
|
|||
ret_ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_cast_fat_pointer, code = E0511)]
|
||||
CastFatPointer {
|
||||
#[diag(codegen_ssa_invalid_monomorphization_cast_wide_pointer, code = E0511)]
|
||||
CastWidePointer {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
|
|
|
@ -156,7 +156,7 @@ pub struct NativeLib {
|
|||
pub kind: NativeLibKind,
|
||||
pub name: Symbol,
|
||||
pub filename: Option<Symbol>,
|
||||
pub cfg: Option<ast::MetaItem>,
|
||||
pub cfg: Option<ast::NestedMetaItem>,
|
||||
pub verbatim: bool,
|
||||
pub dll_imports: Vec<cstore::DllImport>,
|
||||
}
|
||||
|
|
|
@ -133,9 +133,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
enum LocalRef<'tcx, V> {
|
||||
Place(PlaceRef<'tcx, V>),
|
||||
/// `UnsizedPlace(p)`: `p` itself is a thin pointer (indirect place).
|
||||
/// `*p` is the fat pointer that references the actual unsized place.
|
||||
/// `*p` is the wide pointer that references the actual unsized place.
|
||||
/// Every time it is initialized, we have to reallocate the place
|
||||
/// and update the fat pointer. That's the reason why it is indirect.
|
||||
/// and update the wide pointer. That's the reason why it is indirect.
|
||||
UnsizedPlace(PlaceRef<'tcx, V>),
|
||||
/// The backend [`OperandValue`] has already been generated.
|
||||
Operand(OperandRef<'tcx, V>),
|
||||
|
@ -429,7 +429,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
// Unsized indirect qrguments
|
||||
PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
|
||||
// As the storage for the indirect argument lives during
|
||||
// the whole function call, we just copy the fat pointer.
|
||||
// the whole function call, we just copy the wide pointer.
|
||||
let llarg = bx.get_param(llarg_idx);
|
||||
llarg_idx += 1;
|
||||
let llextra = bx.get_param(llarg_idx);
|
||||
|
|
|
@ -41,7 +41,7 @@ pub enum OperandValue<V> {
|
|||
/// The backend value in this variant must be the *immediate* backend type,
|
||||
/// as returned by [`LayoutTypeCodegenMethods::immediate_backend_type`].
|
||||
Immediate(V),
|
||||
/// A pair of immediate LLVM values. Used by fat pointers too.
|
||||
/// A pair of immediate LLVM values. Used by wide pointers too.
|
||||
///
|
||||
/// An `OperandValue` *must* be this variant for any type for which
|
||||
/// [`LayoutTypeCodegenMethods::is_backend_scalar_pair`] returns `true`.
|
||||
|
|
|
@ -38,10 +38,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
ref source,
|
||||
_,
|
||||
) => {
|
||||
// The destination necessarily contains a fat pointer, so if
|
||||
// it's a scalar pair, it's a fat pointer or newtype thereof.
|
||||
// The destination necessarily contains a wide pointer, so if
|
||||
// it's a scalar pair, it's a wide pointer or newtype thereof.
|
||||
if bx.cx().is_backend_scalar_pair(dest.layout) {
|
||||
// Into-coerce of a thin pointer to a fat pointer -- just
|
||||
// Into-coerce of a thin pointer to a wide pointer -- just
|
||||
// use the operand path.
|
||||
let temp = self.codegen_rvalue_operand(bx, rvalue);
|
||||
temp.val.store(bx, dest);
|
||||
|
@ -519,7 +519,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
if bx.cx().is_backend_scalar_pair(cast) {
|
||||
OperandValue::Pair(data_ptr, meta)
|
||||
} else {
|
||||
// Cast of fat-ptr to thin-ptr is an extraction of data-ptr.
|
||||
// Cast of wide-ptr to thin-ptr is an extraction of data-ptr.
|
||||
OperandValue::Immediate(data_ptr)
|
||||
}
|
||||
} else {
|
||||
|
@ -622,7 +622,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
(
|
||||
OperandValue::Pair(lhs_addr, lhs_extra),
|
||||
OperandValue::Pair(rhs_addr, rhs_extra),
|
||||
) => self.codegen_fat_ptr_binop(
|
||||
) => self.codegen_wide_ptr_binop(
|
||||
bx,
|
||||
op,
|
||||
lhs_addr,
|
||||
|
@ -984,7 +984,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn codegen_fat_ptr_binop(
|
||||
fn codegen_wide_ptr_binop(
|
||||
&mut self,
|
||||
bx: &mut Bx,
|
||||
op: mir::BinOp,
|
||||
|
@ -1021,7 +1021,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
bx.or(lhs, rhs)
|
||||
}
|
||||
_ => {
|
||||
bug!("unexpected fat ptr binop");
|
||||
bug!("unexpected wide ptr binop");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -204,12 +204,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
|
||||
assert!(src.layout.ty.is_any_ptr());
|
||||
assert!(cast_to.ty.is_unsafe_ptr());
|
||||
// Handle casting any ptr to raw ptr (might be a fat ptr).
|
||||
// Handle casting any ptr to raw ptr (might be a wide ptr).
|
||||
if cast_to.size == src.layout.size {
|
||||
// Thin or fat pointer that just has the ptr kind of target type changed.
|
||||
// Thin or wide pointer that just has the ptr kind of target type changed.
|
||||
return interp_ok(ImmTy::from_immediate(**src, cast_to));
|
||||
} else {
|
||||
// Casting the metadata away from a fat ptr.
|
||||
// Casting the metadata away from a wide ptr.
|
||||
assert_eq!(src.layout.size, 2 * self.pointer_size());
|
||||
assert_eq!(cast_to.size, self.pointer_size());
|
||||
assert!(src.layout.ty.is_unsafe_ptr());
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
A cast between a thin and a fat pointer was attempted.
|
||||
A cast between a thin and a wide pointer was attempted.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
|
@ -7,18 +7,18 @@ let v = core::ptr::null::<u8>();
|
|||
v as *const [u8];
|
||||
```
|
||||
|
||||
First: what are thin and fat pointers?
|
||||
First: what are thin and wide pointers?
|
||||
|
||||
Thin pointers are "simple" pointers: they are purely a reference to a memory
|
||||
address.
|
||||
|
||||
Fat pointers are pointers referencing Dynamically Sized Types (also called
|
||||
Wide pointers are pointers referencing Dynamically Sized Types (also called
|
||||
DSTs). DSTs don't have a statically known size, therefore they can only exist
|
||||
behind some kind of pointer that contains additional information. For example,
|
||||
slices and trait objects are DSTs. In the case of slices, the additional
|
||||
information the fat pointer holds is their size.
|
||||
information the wide pointer holds is their size.
|
||||
|
||||
To fix this error, don't try to cast directly between thin and fat pointers.
|
||||
To fix this error, don't try to cast directly between thin and wide pointers.
|
||||
|
||||
For more information about type casts, take a look at the section of the
|
||||
[The Rust Reference][1] on type cast expressions.
|
||||
|
|
|
@ -5,7 +5,9 @@ use rustc_ast::token::{Delimiter, Token, TokenKind};
|
|||
use rustc_ast::tokenstream::{
|
||||
AttrTokenStream, AttrTokenTree, LazyAttrTokenStream, Spacing, TokenTree,
|
||||
};
|
||||
use rustc_ast::{self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem, NodeId};
|
||||
use rustc_ast::{
|
||||
self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem, NestedMetaItem, NodeId,
|
||||
};
|
||||
use rustc_attr as attr;
|
||||
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
|
||||
use rustc_feature::{
|
||||
|
@ -449,7 +451,7 @@ impl<'a> StripUnconfigured<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a MetaItem> {
|
||||
pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a NestedMetaItem> {
|
||||
let span = meta_item.span;
|
||||
match meta_item.meta_item_list() {
|
||||
None => {
|
||||
|
@ -464,7 +466,7 @@ pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a Meta
|
|||
sess.dcx().emit_err(InvalidCfg::MultiplePredicates { span: l.span() });
|
||||
None
|
||||
}
|
||||
Some([single]) => match single.meta_item() {
|
||||
Some([single]) => match single.meta_item_or_bool() {
|
||||
Some(meta_item) => Some(meta_item),
|
||||
None => {
|
||||
sess.dcx().emit_err(InvalidCfg::PredicateLiteral { span: single.span() });
|
||||
|
|
|
@ -371,6 +371,8 @@ declare_features! (
|
|||
(unstable, async_for_loop, "1.77.0", Some(118898)),
|
||||
/// Allows using C-variadics.
|
||||
(unstable, c_variadic, "1.34.0", Some(44930)),
|
||||
/// Allows the use of `#[cfg(<true/false>)]`.
|
||||
(unstable, cfg_boolean_literals, "CURRENT_RUSTC_VERSION", Some(131204)),
|
||||
/// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour.
|
||||
(unstable, cfg_overflow_checks, "1.71.0", Some(111466)),
|
||||
/// Provides the relocation model information as cfg entry
|
||||
|
|
|
@ -1105,7 +1105,7 @@ fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
|
|||
// Check that we use types valid for use in the lanes of a SIMD "vector register"
|
||||
// These are scalar types which directly match a "machine" type
|
||||
// Yes: Integers, floats, "thin" pointers
|
||||
// No: char, "fat" pointers, compound types
|
||||
// No: char, "wide" pointers, compound types
|
||||
match element_ty.kind() {
|
||||
ty::Param(_) => (), // pass struct<T>([T; 4]) through, let monomorphization catch errors
|
||||
ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_, _) => (), // struct([u8; 4]) is ok
|
||||
|
|
|
@ -424,7 +424,7 @@ pub(crate) fn coerce_unsized_info<'tcx>(
|
|||
// Here `U = [i32; 3]` and `V = [i32]`. At runtime,
|
||||
// when this coercion occurs, we would be changing the
|
||||
// field `ptr` from a thin pointer of type `*mut [i32;
|
||||
// 3]` to a fat pointer of type `*mut [i32]` (with
|
||||
// 3]` to a wide pointer of type `*mut [i32]` (with
|
||||
// extra data `3`). **The purpose of this check is to
|
||||
// make sure that we know how to do this conversion.**
|
||||
//
|
||||
|
|
|
@ -23,17 +23,17 @@ hir_typeck_cannot_cast_to_bool = cannot cast `{$expr_ty}` as `bool`
|
|||
|
||||
hir_typeck_cast_enum_drop = cannot cast enum `{$expr_ty}` into integer `{$cast_ty}` because it implements `Drop`
|
||||
|
||||
hir_typeck_cast_thin_pointer_to_fat_pointer = cannot cast thin pointer `{$expr_ty}` to fat pointer `{$cast_ty}`
|
||||
hir_typeck_cast_thin_pointer_to_wide_pointer = cannot cast thin pointer `{$expr_ty}` to wide pointer `{$cast_ty}`
|
||||
.teach_help = Thin pointers are "simple" pointers: they are purely a reference to a
|
||||
memory address.
|
||||
|
||||
Fat pointers are pointers referencing "Dynamically Sized Types" (also
|
||||
Wide pointers are pointers referencing "Dynamically Sized Types" (also
|
||||
called DST). DST don't have a statically known size, therefore they can
|
||||
only exist behind some kind of pointers that contain additional
|
||||
information. Slices and trait objects are DSTs. In the case of slices,
|
||||
the additional information the fat pointer holds is their size.
|
||||
the additional information the wide pointer holds is their size.
|
||||
|
||||
To fix this error, don't try to cast directly between thin and fat
|
||||
To fix this error, don't try to cast directly between thin and wide
|
||||
pointers.
|
||||
|
||||
For more information about casts, take a look at The Book:
|
||||
|
|
|
@ -66,7 +66,7 @@ pub(crate) struct CastCheck<'tcx> {
|
|||
}
|
||||
|
||||
/// The kind of pointer and associated metadata (thin, length or vtable) - we
|
||||
/// only allow casts between fat pointers if their metadata have the same
|
||||
/// only allow casts between wide pointers if their metadata have the same
|
||||
/// kind.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, TypeVisitable, TypeFoldable)]
|
||||
enum PointerKind<'tcx> {
|
||||
|
@ -162,7 +162,7 @@ enum CastError<'tcx> {
|
|||
src_kind: PointerKind<'tcx>,
|
||||
dst_kind: PointerKind<'tcx>,
|
||||
},
|
||||
/// Cast of thin to fat raw ptr (e.g., `*const () as *const [u8]`).
|
||||
/// Cast of thin to wide raw ptr (e.g., `*const () as *const [u8]`).
|
||||
SizedUnsizedCast,
|
||||
IllegalCast,
|
||||
NeedDeref,
|
||||
|
@ -172,12 +172,12 @@ enum CastError<'tcx> {
|
|||
NonScalar,
|
||||
UnknownExprPtrKind,
|
||||
UnknownCastPtrKind,
|
||||
/// Cast of int to (possibly) fat raw pointer.
|
||||
/// Cast of int to (possibly) wide raw pointer.
|
||||
///
|
||||
/// Argument is the specific name of the metadata in plain words, such as "a vtable"
|
||||
/// or "a length". If this argument is None, then the metadata is unknown, for example,
|
||||
/// when we're typechecking a type parameter with a ?Sized bound.
|
||||
IntToFatCast(Option<&'static str>),
|
||||
IntToWideCast(Option<&'static str>),
|
||||
ForeignNonExhaustiveAdt,
|
||||
}
|
||||
|
||||
|
@ -545,14 +545,14 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
err.emit();
|
||||
}
|
||||
CastError::SizedUnsizedCast => {
|
||||
fcx.dcx().emit_err(errors::CastThinPointerToFatPointer {
|
||||
fcx.dcx().emit_err(errors::CastThinPointerToWidePointer {
|
||||
span: self.span,
|
||||
expr_ty: self.expr_ty,
|
||||
cast_ty: fcx.ty_to_string(self.cast_ty),
|
||||
teach: fcx.tcx.sess.teach(E0607),
|
||||
});
|
||||
}
|
||||
CastError::IntToFatCast(known_metadata) => {
|
||||
CastError::IntToWideCast(known_metadata) => {
|
||||
let expr_if_nightly = fcx.tcx.sess.is_nightly_build().then_some(self.expr_span);
|
||||
let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty);
|
||||
let expr_ty = fcx.ty_to_string(self.expr_ty);
|
||||
|
@ -861,7 +861,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
return Ok(CastKind::PtrPtrCast);
|
||||
}
|
||||
|
||||
// We can't cast to fat pointer if source pointer kind is unknown
|
||||
// We can't cast to wide pointer if source pointer kind is unknown
|
||||
let Some(src_kind) = src_kind else {
|
||||
return Err(CastError::UnknownCastPtrKind);
|
||||
};
|
||||
|
@ -1054,10 +1054,10 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||
match fcx.pointer_kind(m_cast.ty, self.span)? {
|
||||
None => Err(CastError::UnknownCastPtrKind),
|
||||
Some(PointerKind::Thin) => Ok(CastKind::AddrPtrCast),
|
||||
Some(PointerKind::VTable(_)) => Err(CastError::IntToFatCast(Some("a vtable"))),
|
||||
Some(PointerKind::Length) => Err(CastError::IntToFatCast(Some("a length"))),
|
||||
Some(PointerKind::VTable(_)) => Err(CastError::IntToWideCast(Some("a vtable"))),
|
||||
Some(PointerKind::Length) => Err(CastError::IntToWideCast(Some("a length"))),
|
||||
Some(PointerKind::OfAlias(_) | PointerKind::OfParam(_)) => {
|
||||
Err(CastError::IntToFatCast(None))
|
||||
Err(CastError::IntToWideCast(None))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -699,8 +699,8 @@ pub(crate) struct ReplaceWithName {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_cast_thin_pointer_to_fat_pointer, code = E0607)]
|
||||
pub(crate) struct CastThinPointerToFatPointer<'tcx> {
|
||||
#[diag(hir_typeck_cast_thin_pointer_to_wide_pointer, code = E0607)]
|
||||
pub(crate) struct CastThinPointerToWidePointer<'tcx> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub expr_ty: Ty<'tcx>,
|
||||
|
|
|
@ -55,7 +55,7 @@ impl<'a, 'tcx> Expectation<'tcx> {
|
|||
/// be checked higher up, as is the case with `&expr` and `box expr`), but
|
||||
/// is useful in determining the concrete type.
|
||||
///
|
||||
/// The primary use case is where the expected type is a fat pointer,
|
||||
/// The primary use case is where the expected type is a wide pointer,
|
||||
/// like `&[isize]`. For example, consider the following statement:
|
||||
///
|
||||
/// let x: &[isize] = &[1, 2, 3];
|
||||
|
|
|
@ -413,7 +413,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
ty::Ref(_, ty, _) | ty::RawPtr(ty, _) => {
|
||||
if oprnd.is_syntactic_place_expr() {
|
||||
// Places may legitimately have unsized types.
|
||||
// For example, dereferences of a fat pointer and
|
||||
// For example, dereferences of a wide pointer and
|
||||
// the last field of a struct can be unsized.
|
||||
ExpectHasType(*ty)
|
||||
} else {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::ops::ControlFlow;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use rustc_ast::{CRATE_NODE_ID, NestedMetaItem};
|
||||
use rustc_ast::CRATE_NODE_ID;
|
||||
use rustc_attr as attr;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_middle::query::LocalCrate;
|
||||
|
@ -304,7 +304,12 @@ impl<'tcx> Collector<'tcx> {
|
|||
sess.dcx().emit_err(errors::LinkCfgForm { span: item.span() });
|
||||
continue;
|
||||
};
|
||||
let [NestedMetaItem::MetaItem(link_cfg)] = link_cfg else {
|
||||
let [link_cfg] = link_cfg else {
|
||||
sess.dcx()
|
||||
.emit_err(errors::LinkCfgSinglePredicate { span: item.span() });
|
||||
continue;
|
||||
};
|
||||
let Some(link_cfg) = link_cfg.meta_item_or_bool() else {
|
||||
sess.dcx()
|
||||
.emit_err(errors::LinkCfgSinglePredicate { span: item.span() });
|
||||
continue;
|
||||
|
|
|
@ -25,10 +25,10 @@ pub enum PointerCoercion {
|
|||
ArrayToPointer,
|
||||
|
||||
/// Unsize a pointer/reference value, e.g., `&[T; n]` to
|
||||
/// `&[T]`. Note that the source could be a thin or fat pointer.
|
||||
/// This will do things like convert thin pointers to fat
|
||||
/// `&[T]`. Note that the source could be a thin or wide pointer.
|
||||
/// This will do things like convert thin pointers to wide
|
||||
/// pointers, or convert structs containing thin pointers to
|
||||
/// structs containing fat pointers, or convert between fat
|
||||
/// structs containing wide pointers, or convert between wide
|
||||
/// pointers. We don't store the details of how the transform is
|
||||
/// done (in fact, we don't know that, because it might depend on
|
||||
/// the precise type parameters). We just store the target
|
||||
|
|
|
@ -164,17 +164,17 @@ impl Primitive {
|
|||
}
|
||||
}
|
||||
|
||||
/// The first half of a fat pointer.
|
||||
/// The first half of a wide pointer.
|
||||
///
|
||||
/// - For a trait object, this is the address of the box.
|
||||
/// - For a slice, this is the base address.
|
||||
pub const FAT_PTR_ADDR: usize = 0;
|
||||
pub const WIDE_PTR_ADDR: usize = 0;
|
||||
|
||||
/// The second half of a fat pointer.
|
||||
/// The second half of a wide pointer.
|
||||
///
|
||||
/// - For a trait object, this is the address of the vtable.
|
||||
/// - For a slice, this is the length.
|
||||
pub const FAT_PTR_EXTRA: usize = 1;
|
||||
pub const WIDE_PTR_EXTRA: usize = 1;
|
||||
|
||||
/// The maximum supported number of lanes in a SIMD vector.
|
||||
///
|
||||
|
@ -312,7 +312,7 @@ pub enum SizeSkeleton<'tcx> {
|
|||
/// that another SizeSkeleton is of equal size.
|
||||
Generic(ty::Const<'tcx>),
|
||||
|
||||
/// A potentially-fat pointer.
|
||||
/// A potentially-wide pointer.
|
||||
Pointer {
|
||||
/// If true, this pointer is never null.
|
||||
non_zero: bool,
|
||||
|
@ -785,11 +785,11 @@ where
|
|||
bug!("TyAndLayout::field({:?}): not applicable", this)
|
||||
}
|
||||
|
||||
// Potentially-fat pointers.
|
||||
// Potentially-wide pointers.
|
||||
ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => {
|
||||
assert!(i < this.fields.count());
|
||||
|
||||
// Reuse the fat `*T` type as its own thin pointer data field.
|
||||
// Reuse the wide `*T` type as its own thin pointer data field.
|
||||
// This provides information about, e.g., DST struct pointees
|
||||
// (which may have no non-DST form), and will work as long
|
||||
// as the `Abi` or `FieldsShape` is checked by users.
|
||||
|
|
|
@ -1589,7 +1589,7 @@ impl<'tcx> Ty<'tcx> {
|
|||
.map_bound(|fn_sig| fn_sig.output().no_bound_vars().unwrap())
|
||||
}
|
||||
|
||||
/// Returns the type of metadata for (potentially fat) pointers to this type,
|
||||
/// Returns the type of metadata for (potentially wide) pointers to this type,
|
||||
/// or the struct tail if the metadata type cannot be determined.
|
||||
pub fn ptr_metadata_ty_or_tail(
|
||||
self,
|
||||
|
@ -1648,7 +1648,7 @@ impl<'tcx> Ty<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the type of metadata for (potentially fat) pointers to this type.
|
||||
/// Returns the type of metadata for (potentially wide) pointers to this type.
|
||||
/// Causes an ICE if the metadata type cannot be determined.
|
||||
pub fn ptr_metadata_ty(
|
||||
self,
|
||||
|
|
|
@ -1137,7 +1137,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
(UnOp::PtrMetadata, Value::Aggregate(AggregateTy::RawPtr { .. }, _, fields)) => {
|
||||
return Some(fields[1]);
|
||||
}
|
||||
// We have an unsizing cast, which assigns the length to fat pointer metadata.
|
||||
// We have an unsizing cast, which assigns the length to wide pointer metadata.
|
||||
(
|
||||
UnOp::PtrMetadata,
|
||||
Value::Cast {
|
||||
|
@ -1421,7 +1421,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
|
||||
let mut inner = self.simplify_place_value(place, location)?;
|
||||
|
||||
// The length information is stored in the fat pointer.
|
||||
// The length information is stored in the wide pointer.
|
||||
// Reborrowing copies length information from one pointer to the other.
|
||||
while let Value::Address { place: borrowed, .. } = self.get(inner)
|
||||
&& let [PlaceElem::Deref] = borrowed.projection[..]
|
||||
|
@ -1430,7 +1430,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||
inner = borrowed;
|
||||
}
|
||||
|
||||
// We have an unsizing cast, which assigns the length to fat pointer metadata.
|
||||
// We have an unsizing cast, which assigns the length to wide pointer metadata.
|
||||
if let Value::Cast { kind, from, to, .. } = self.get(inner)
|
||||
&& let CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _) = kind
|
||||
&& let Some(from) = from.builtin_deref(true)
|
||||
|
|
|
@ -119,7 +119,7 @@
|
|||
//!
|
||||
//! #### Unsizing Casts
|
||||
//! A subtle way of introducing use edges is by casting to a trait object.
|
||||
//! Since the resulting fat-pointer contains a reference to a vtable, we need to
|
||||
//! Since the resulting wide-pointer contains a reference to a vtable, we need to
|
||||
//! instantiate all dyn-compatible methods of the trait, as we need to store
|
||||
//! pointers to these functions even if they never get called anywhere. This can
|
||||
//! be seen as a special case of taking a function reference.
|
||||
|
@ -661,7 +661,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
|
|||
let span = self.body.source_info(location).span;
|
||||
|
||||
match *rvalue {
|
||||
// When doing an cast from a regular pointer to a fat pointer, we
|
||||
// When doing an cast from a regular pointer to a wide pointer, we
|
||||
// have to instantiate all methods of the trait being cast to, so we
|
||||
// can build the appropriate vtable.
|
||||
mir::Rvalue::Cast(
|
||||
|
@ -985,7 +985,7 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxtAt<'tcx>, instance: Instance<'tcx>) -
|
|||
/// ```
|
||||
///
|
||||
/// Then the output of this function would be (SomeStruct, SomeTrait) since for
|
||||
/// constructing the `target` fat-pointer we need the vtable for that pair.
|
||||
/// constructing the `target` wide-pointer we need the vtable for that pair.
|
||||
///
|
||||
/// Things can get more complicated though because there's also the case where
|
||||
/// the unsized type occurs as a field:
|
||||
|
@ -999,7 +999,7 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxtAt<'tcx>, instance: Instance<'tcx>) -
|
|||
/// ```
|
||||
///
|
||||
/// In this case, if `T` is sized, `&ComplexStruct<T>` is a thin pointer. If `T`
|
||||
/// is unsized, `&SomeStruct` is a fat pointer, and the vtable it points to is
|
||||
/// is unsized, `&SomeStruct` is a wide pointer, and the vtable it points to is
|
||||
/// for the pair of `T` (which is a trait) and the concrete type that `T` was
|
||||
/// originally coerced from:
|
||||
///
|
||||
|
|
|
@ -18,7 +18,7 @@ use std::path::Path;
|
|||
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::{AttrItem, Attribute, MetaItem, token};
|
||||
use rustc_ast::{AttrItem, Attribute, NestedMetaItem, token};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::{Diag, FatalError, PResult};
|
||||
|
@ -160,7 +160,7 @@ pub fn fake_token_stream_for_crate(psess: &ParseSess, krate: &ast::Crate) -> Tok
|
|||
pub fn parse_cfg_attr(
|
||||
cfg_attr: &Attribute,
|
||||
psess: &ParseSess,
|
||||
) -> Option<(MetaItem, Vec<(AttrItem, Span)>)> {
|
||||
) -> Option<(NestedMetaItem, Vec<(AttrItem, Span)>)> {
|
||||
const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]";
|
||||
const CFG_ATTR_NOTE_REF: &str = "for more information, visit \
|
||||
<https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>";
|
||||
|
|
|
@ -356,8 +356,10 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
/// Parses `cfg_attr(pred, attr_item_list)` where `attr_item_list` is comma-delimited.
|
||||
pub fn parse_cfg_attr(&mut self) -> PResult<'a, (ast::MetaItem, Vec<(ast::AttrItem, Span)>)> {
|
||||
let cfg_predicate = self.parse_meta_item(AllowLeadingUnsafe::No)?;
|
||||
pub fn parse_cfg_attr(
|
||||
&mut self,
|
||||
) -> PResult<'a, (ast::NestedMetaItem, Vec<(ast::AttrItem, Span)>)> {
|
||||
let cfg_predicate = self.parse_meta_item_inner()?;
|
||||
self.expect(&token::Comma)?;
|
||||
|
||||
// Presumably, the majority of the time there will only be one attr.
|
||||
|
@ -452,7 +454,7 @@ impl<'a> Parser<'a> {
|
|||
/// ```ebnf
|
||||
/// MetaItemInner = UNSUFFIXED_LIT | MetaItem ;
|
||||
/// ```
|
||||
fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::NestedMetaItem> {
|
||||
pub fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::NestedMetaItem> {
|
||||
match self.parse_unsuffixed_meta_item_lit() {
|
||||
Ok(lit) => return Ok(ast::NestedMetaItem::Lit(lit)),
|
||||
Err(err) => err.cancel(), // we provide a better error below
|
||||
|
|
|
@ -72,7 +72,7 @@ pub struct NativeLib {
|
|||
pub name: Symbol,
|
||||
/// If packed_bundled_libs enabled, actual filename of library is stored.
|
||||
pub filename: Option<Symbol>,
|
||||
pub cfg: Option<ast::MetaItem>,
|
||||
pub cfg: Option<ast::NestedMetaItem>,
|
||||
pub foreign_module: Option<DefId>,
|
||||
pub verbatim: Option<bool>,
|
||||
pub dll_imports: Vec<DllImport>,
|
||||
|
|
|
@ -544,6 +544,7 @@ symbols! {
|
|||
cfg_accessible,
|
||||
cfg_attr,
|
||||
cfg_attr_multi,
|
||||
cfg_boolean_literals,
|
||||
cfg_doctest,
|
||||
cfg_eval,
|
||||
cfg_fmt_debug,
|
||||
|
|
|
@ -637,7 +637,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Pass this argument indirectly, by passing a (thin or fat) pointer to the argument instead.
|
||||
/// Pass this argument indirectly, by passing a (thin or wide) pointer to the argument instead.
|
||||
/// This is valid for both sized and unsized arguments.
|
||||
pub fn make_indirect(&mut self) {
|
||||
match self.mode {
|
||||
|
|
|
@ -135,7 +135,7 @@ impl<'a> Layout<'a> {
|
|||
/// Note that the layout is NOT guaranteed to always be identical
|
||||
/// to that obtained from `layout_of(ty)`, as we need to produce
|
||||
/// layouts for which Rust types do not exist, such as enum variants
|
||||
/// or synthetic fields of enums (i.e., discriminants) and fat pointers.
|
||||
/// or synthetic fields of enums (i.e., discriminants) and wide pointers.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)]
|
||||
pub struct TyAndLayout<'a, Ty> {
|
||||
pub ty: Ty,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::iter;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind, Attribute, MetaItem, NestedMetaItem};
|
||||
use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind, Attribute, NestedMetaItem};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{ErrorGuaranteed, struct_span_code_err};
|
||||
|
@ -282,7 +282,7 @@ pub struct OnUnimplementedFormatString {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct OnUnimplementedDirective {
|
||||
pub condition: Option<MetaItem>,
|
||||
pub condition: Option<NestedMetaItem>,
|
||||
pub subcommands: Vec<OnUnimplementedDirective>,
|
||||
pub message: Option<OnUnimplementedFormatString>,
|
||||
pub label: Option<OnUnimplementedFormatString>,
|
||||
|
@ -414,7 +414,7 @@ impl<'tcx> OnUnimplementedDirective {
|
|||
let cond = item_iter
|
||||
.next()
|
||||
.ok_or_else(|| tcx.dcx().emit_err(EmptyOnClauseInOnUnimplemented { span }))?
|
||||
.meta_item()
|
||||
.meta_item_or_bool()
|
||||
.ok_or_else(|| tcx.dcx().emit_err(InvalidOnClauseInOnUnimplemented { span }))?;
|
||||
attr::eval_condition(cond, &tcx.sess, Some(tcx.features()), &mut |cfg| {
|
||||
if let Some(value) = cfg.value
|
||||
|
@ -558,8 +558,8 @@ impl<'tcx> OnUnimplementedDirective {
|
|||
IgnoredDiagnosticOption::maybe_emit_warning(
|
||||
tcx,
|
||||
item_def_id,
|
||||
directive.condition.as_ref().map(|i| i.span),
|
||||
aggr.condition.as_ref().map(|i| i.span),
|
||||
directive.condition.as_ref().map(|i| i.span()),
|
||||
aggr.condition.as_ref().map(|i| i.span()),
|
||||
"condition",
|
||||
);
|
||||
IgnoredDiagnosticOption::maybe_emit_warning(
|
||||
|
|
|
@ -357,7 +357,7 @@ fn fn_abi_of_instance<'tcx>(
|
|||
)
|
||||
}
|
||||
|
||||
// Handle safe Rust thin and fat pointers.
|
||||
// Handle safe Rust thin and wide pointers.
|
||||
fn adjust_for_rust_scalar<'tcx>(
|
||||
cx: LayoutCx<'tcx>,
|
||||
attrs: &mut ArgAttributes,
|
||||
|
@ -810,7 +810,7 @@ fn make_thin_self_ptr<'tcx>(
|
|||
layout: TyAndLayout<'tcx>,
|
||||
) -> TyAndLayout<'tcx> {
|
||||
let tcx = cx.tcx();
|
||||
let fat_pointer_ty = if layout.is_unsized() {
|
||||
let wide_pointer_ty = if layout.is_unsized() {
|
||||
// unsized `self` is passed as a pointer to `self`
|
||||
// FIXME (mikeyhew) change this to use &own if it is ever added to the language
|
||||
Ty::new_mut_ptr(tcx, layout.ty)
|
||||
|
@ -825,15 +825,15 @@ fn make_thin_self_ptr<'tcx>(
|
|||
// elsewhere in the compiler as a method on a `dyn Trait`.
|
||||
// To get the type `*mut RcBox<Self>`, we just keep unwrapping newtypes until we
|
||||
// get a built-in pointer type
|
||||
let mut fat_pointer_layout = layout;
|
||||
while !fat_pointer_layout.ty.is_unsafe_ptr() && !fat_pointer_layout.ty.is_ref() {
|
||||
fat_pointer_layout = fat_pointer_layout
|
||||
let mut wide_pointer_layout = layout;
|
||||
while !wide_pointer_layout.ty.is_unsafe_ptr() && !wide_pointer_layout.ty.is_ref() {
|
||||
wide_pointer_layout = wide_pointer_layout
|
||||
.non_1zst_field(cx)
|
||||
.expect("not exactly one non-1-ZST field in a `DispatchFromDyn` type")
|
||||
.1
|
||||
}
|
||||
|
||||
fat_pointer_layout.ty
|
||||
wide_pointer_layout.ty
|
||||
};
|
||||
|
||||
// we now have a type like `*mut RcBox<dyn Trait>`
|
||||
|
@ -842,7 +842,7 @@ fn make_thin_self_ptr<'tcx>(
|
|||
let unit_ptr_ty = Ty::new_mut_ptr(tcx, tcx.types.unit);
|
||||
|
||||
TyAndLayout {
|
||||
ty: fat_pointer_ty,
|
||||
ty: wide_pointer_ty,
|
||||
|
||||
// NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing the `Result`
|
||||
// should always work because the type is always `*mut ()`.
|
||||
|
|
|
@ -946,10 +946,10 @@ pub enum PointerCoercion {
|
|||
ArrayToPointer,
|
||||
|
||||
/// Unsize a pointer/reference value, e.g., `&[T; n]` to
|
||||
/// `&[T]`. Note that the source could be a thin or fat pointer.
|
||||
/// This will do things like convert thin pointers to fat
|
||||
/// `&[T]`. Note that the source could be a thin or wide pointer.
|
||||
/// This will do things like convert thin pointers to wide
|
||||
/// pointers, or convert structs containing thin pointers to
|
||||
/// structs containing fat pointers, or convert between fat
|
||||
/// structs containing wide pointers, or convert between wide
|
||||
/// pointers.
|
||||
Unsize,
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue