mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
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
@ -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,
|
||||
}
|
||||
|
@ -100,4 +100,4 @@ RUN /scripts/build-gccjit.sh /scripts
|
||||
# the local version of the package is different than the one used by the CI.
|
||||
ENV SCRIPT /tmp/checktools.sh ../x.py && \
|
||||
npm install browser-ui-test@$(head -n 1 /tmp/browser-ui-test.version) --unsafe-perm=true && \
|
||||
python3 ../x.py test tests/rustdoc-gui --stage 2 --test-args "'--no-sandbox --jobs 1'"
|
||||
python3 ../x.py test tests/rustdoc-gui --stage 2 --test-args "'--jobs 1'"
|
||||
|
@ -0,0 +1,22 @@
|
||||
# `cfg_boolean_literals`
|
||||
|
||||
The tracking issue for this feature is: [#131204]
|
||||
|
||||
[#131204]: https://github.com/rust-lang/rust/issues/131204
|
||||
|
||||
------------------------
|
||||
|
||||
The `cfg_boolean_literals` feature makes it possible to use the `true`/`false`
|
||||
literal as cfg predicate. They always evaluate to true/false respectively.
|
||||
|
||||
## Examples
|
||||
|
||||
```rust
|
||||
#![feature(cfg_boolean_literals)]
|
||||
|
||||
#[cfg(true)]
|
||||
const A: i32 = 5;
|
||||
|
||||
#[cfg(all(false))]
|
||||
const A: i32 = 58 * 89;
|
||||
```
|
@ -6,7 +6,7 @@
|
||||
use std::fmt::{self, Write};
|
||||
use std::{mem, ops};
|
||||
|
||||
use rustc_ast::{LitKind, MetaItem, MetaItemKind, NestedMetaItem};
|
||||
use rustc_ast::{LitKind, MetaItem, MetaItemKind, MetaItemLit, NestedMetaItem};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_feature::Features;
|
||||
use rustc_session::parse::ParseSess;
|
||||
@ -48,6 +48,10 @@ impl Cfg {
|
||||
) -> Result<Option<Cfg>, InvalidCfgError> {
|
||||
match nested_cfg {
|
||||
NestedMetaItem::MetaItem(ref cfg) => Cfg::parse_without(cfg, exclude),
|
||||
NestedMetaItem::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => match *b {
|
||||
true => Ok(Some(Cfg::True)),
|
||||
false => Ok(Some(Cfg::False)),
|
||||
},
|
||||
NestedMetaItem::Lit(ref lit) => {
|
||||
Err(InvalidCfgError { msg: "unexpected literal", span: lit.span })
|
||||
}
|
||||
@ -120,8 +124,8 @@ impl Cfg {
|
||||
///
|
||||
/// If the content is not properly formatted, it will return an error indicating what and where
|
||||
/// the error is.
|
||||
pub(crate) fn parse(cfg: &MetaItem) -> Result<Cfg, InvalidCfgError> {
|
||||
Self::parse_without(cfg, &FxHashSet::default()).map(|ret| ret.unwrap())
|
||||
pub(crate) fn parse(cfg: &NestedMetaItem) -> Result<Cfg, InvalidCfgError> {
|
||||
Self::parse_nested(cfg, &FxHashSet::default()).map(|ret| ret.unwrap())
|
||||
}
|
||||
|
||||
/// Checks whether the given configuration can be matched in the current session.
|
||||
|
@ -1,4 +1,5 @@
|
||||
use rustc_ast::{MetaItemLit, Path, Safety, StrStyle};
|
||||
use rustc_ast::ast::LitIntType;
|
||||
use rustc_ast::{MetaItemLit, NestedMetaItem, Path, Safety, StrStyle};
|
||||
use rustc_span::symbol::{Ident, kw};
|
||||
use rustc_span::{DUMMY_SP, create_default_session_globals_then};
|
||||
use thin_vec::thin_vec;
|
||||
@ -13,52 +14,52 @@ fn name_value_cfg(name: &str, value: &str) -> Cfg {
|
||||
Cfg::Cfg(Symbol::intern(name), Some(Symbol::intern(value)))
|
||||
}
|
||||
|
||||
fn dummy_meta_item_word(name: &str) -> MetaItem {
|
||||
MetaItem {
|
||||
fn dummy_lit(symbol: Symbol, kind: LitKind) -> NestedMetaItem {
|
||||
NestedMetaItem::Lit(MetaItemLit { symbol, suffix: None, kind, span: DUMMY_SP })
|
||||
}
|
||||
|
||||
fn dummy_meta_item_word(name: &str) -> NestedMetaItem {
|
||||
NestedMetaItem::MetaItem(MetaItem {
|
||||
unsafety: Safety::Default,
|
||||
path: Path::from_ident(Ident::from_str(name)),
|
||||
kind: MetaItemKind::Word,
|
||||
span: DUMMY_SP,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn dummy_meta_item_name_value(name: &str, symbol: Symbol, kind: LitKind) -> MetaItem {
|
||||
fn dummy_meta_item_name_value(name: &str, symbol: Symbol, kind: LitKind) -> NestedMetaItem {
|
||||
let lit = MetaItemLit { symbol, suffix: None, kind, span: DUMMY_SP };
|
||||
MetaItem {
|
||||
NestedMetaItem::MetaItem(MetaItem {
|
||||
unsafety: Safety::Default,
|
||||
path: Path::from_ident(Ident::from_str(name)),
|
||||
kind: MetaItemKind::NameValue(lit),
|
||||
span: DUMMY_SP,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
macro_rules! dummy_meta_item_list {
|
||||
($name:ident, [$($list:ident),* $(,)?]) => {
|
||||
MetaItem {
|
||||
NestedMetaItem::MetaItem(MetaItem {
|
||||
unsafety: Safety::Default,
|
||||
path: Path::from_ident(Ident::from_str(stringify!($name))),
|
||||
kind: MetaItemKind::List(thin_vec![
|
||||
$(
|
||||
NestedMetaItem::MetaItem(
|
||||
dummy_meta_item_word(stringify!($list)),
|
||||
),
|
||||
)*
|
||||
]),
|
||||
span: DUMMY_SP,
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
($name:ident, [$($list:expr),* $(,)?]) => {
|
||||
MetaItem {
|
||||
NestedMetaItem::MetaItem(MetaItem {
|
||||
unsafety: Safety::Default,
|
||||
path: Path::from_ident(Ident::from_str(stringify!($name))),
|
||||
kind: MetaItemKind::List(thin_vec![
|
||||
$(
|
||||
NestedMetaItem::MetaItem($list),
|
||||
)*
|
||||
$($list,)*
|
||||
]),
|
||||
span: DUMMY_SP,
|
||||
}
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
@ -251,6 +252,14 @@ fn test_cfg_or() {
|
||||
#[test]
|
||||
fn test_parse_ok() {
|
||||
create_default_session_globals_then(|| {
|
||||
let r#true = Symbol::intern("true");
|
||||
let mi = dummy_lit(r#true, LitKind::Bool(true));
|
||||
assert_eq!(Cfg::parse(&mi), Ok(Cfg::True));
|
||||
|
||||
let r#false = Symbol::intern("false");
|
||||
let mi = dummy_lit(r#false, LitKind::Bool(false));
|
||||
assert_eq!(Cfg::parse(&mi), Ok(Cfg::False));
|
||||
|
||||
let mi = dummy_meta_item_word("all");
|
||||
assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all")));
|
||||
|
||||
@ -309,6 +318,14 @@ fn test_parse_err() {
|
||||
|
||||
let mi = dummy_meta_item_list!(not, [dummy_meta_item_list!(foo, []),]);
|
||||
assert!(Cfg::parse(&mi).is_err());
|
||||
|
||||
let c = Symbol::intern("e");
|
||||
let mi = dummy_lit(c, LitKind::Char('e'));
|
||||
assert!(Cfg::parse(&mi).is_err());
|
||||
|
||||
let five = Symbol::intern("5");
|
||||
let mi = dummy_lit(five, LitKind::Int(5.into(), LitIntType::Unsuffixed));
|
||||
assert!(Cfg::parse(&mi).is_err());
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ use std::sync::{Arc, OnceLock as OnceCell};
|
||||
use std::{fmt, iter};
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
use rustc_ast::NestedMetaItem;
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_attr::{ConstStability, Deprecation, Stability, StableSince};
|
||||
use rustc_const_eval::const_eval::is_unstable_const_fn;
|
||||
@ -986,7 +987,7 @@ pub(crate) trait AttributesExt {
|
||||
.peekable();
|
||||
if doc_cfg.peek().is_some() && doc_cfg_active {
|
||||
doc_cfg
|
||||
.filter_map(|attr| Cfg::parse(attr.meta_item()?).ok())
|
||||
.filter_map(|attr| Cfg::parse(&attr).ok())
|
||||
.fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
|
||||
} else if doc_auto_cfg_active {
|
||||
// If there is no `doc(cfg())`, then we retrieve the `cfg()` attributes (because
|
||||
@ -1042,7 +1043,7 @@ pub(crate) trait AttributesExt {
|
||||
let mut meta = attr.meta_item().unwrap().clone();
|
||||
meta.path = ast::Path::from_ident(Ident::with_dummy_span(sym::target_feature));
|
||||
|
||||
if let Ok(feat_cfg) = Cfg::parse(&meta) {
|
||||
if let Ok(feat_cfg) = Cfg::parse(&NestedMetaItem::MetaItem(meta)) {
|
||||
cfg &= feat_cfg;
|
||||
}
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
.unwrap_or(&[])
|
||||
.iter()
|
||||
.filter_map(|attr| {
|
||||
Cfg::parse(attr.meta_item()?)
|
||||
Cfg::parse(attr)
|
||||
.map_err(|e| self.cx.sess().dcx().span_err(e.span, e.msg))
|
||||
.ok()
|
||||
})
|
||||
|
@ -19,7 +19,6 @@ function showHelp() {
|
||||
console.log(" --debug : show extra information about script run");
|
||||
console.log(" --show-text : render font in pages");
|
||||
console.log(" --no-headless : disable headless mode");
|
||||
console.log(" --no-sandbox : disable sandbox mode");
|
||||
console.log(" --help : show this message then quit");
|
||||
console.log(" --tests-folder [PATH] : location of the .GOML tests folder");
|
||||
console.log(" --jobs [NUMBER] : number of threads to run tests on");
|
||||
@ -40,7 +39,6 @@ function parseOptions(args) {
|
||||
"no_headless": false,
|
||||
"jobs": -1,
|
||||
"executable_path": null,
|
||||
"no_sandbox": false,
|
||||
};
|
||||
const correspondences = {
|
||||
"--doc-folder": "doc_folder",
|
||||
@ -49,7 +47,6 @@ function parseOptions(args) {
|
||||
"--show-text": "show_text",
|
||||
"--no-headless": "no_headless",
|
||||
"--executable-path": "executable_path",
|
||||
"--no-sandbox": "no_sandbox",
|
||||
};
|
||||
|
||||
for (let i = 0; i < args.length; ++i) {
|
||||
@ -80,9 +77,6 @@ function parseOptions(args) {
|
||||
} else if (arg === "--help") {
|
||||
showHelp();
|
||||
process.exit(0);
|
||||
} else if (arg === "--no-sandbox") {
|
||||
console.log("`--no-sandbox` is being used. Be very careful!");
|
||||
opts[correspondences[arg]] = true;
|
||||
} else if (correspondences[arg]) {
|
||||
opts[correspondences[arg]] = true;
|
||||
} else {
|
||||
@ -203,6 +197,7 @@ async function main(argv) {
|
||||
const args = [
|
||||
"--variable", "DOC_PATH", opts["doc_folder"].split("\\").join("/"),
|
||||
"--enable-fail-on-js-error", "--allow-file-access-from-files",
|
||||
"--no-sandbox",
|
||||
];
|
||||
if (opts["debug"]) {
|
||||
debug = true;
|
||||
@ -211,9 +206,6 @@ async function main(argv) {
|
||||
if (opts["show_text"]) {
|
||||
args.push("--show-text");
|
||||
}
|
||||
if (opts["no_sandbox"]) {
|
||||
args.push("--no-sandbox");
|
||||
}
|
||||
if (opts["no_headless"]) {
|
||||
args.push("--no-headless");
|
||||
headless = false;
|
||||
@ -262,19 +254,6 @@ async function main(argv) {
|
||||
console.log(`Running ${files.length} rustdoc-gui ...`);
|
||||
}
|
||||
|
||||
// We catch this "event" to display a nicer message in case of unexpected exit (because of a
|
||||
// missing `--no-sandbox`).
|
||||
const exitHandling = () => {
|
||||
if (!opts["no_sandbox"]) {
|
||||
console.log("");
|
||||
console.log(
|
||||
"`browser-ui-test` crashed unexpectedly. Please try again with adding `--test-args \
|
||||
--no-sandbox` at the end. For example: `x.py test tests/rustdoc-gui --test-args --no-sandbox`");
|
||||
console.log("");
|
||||
}
|
||||
};
|
||||
process.on("exit", exitHandling);
|
||||
|
||||
const originalFilesLen = files.length;
|
||||
const results = createEmptyResults();
|
||||
const status_bar = char_printer(files.length);
|
||||
@ -299,9 +278,6 @@ async function main(argv) {
|
||||
Array.prototype.push.apply(results.failed, new_results.failed);
|
||||
Array.prototype.push.apply(results.errored, new_results.errored);
|
||||
|
||||
// We don't need this listener anymore.
|
||||
process.removeListener("exit", exitHandling);
|
||||
|
||||
if (debug) {
|
||||
results.successful.sort(by_filename);
|
||||
results.successful.forEach(r => {
|
||||
|
@ -23,12 +23,5 @@ $ ./x.py test tests/rustdoc-gui --stage 1 --test-args --no-headless
|
||||
|
||||
To see the supported options, use `--help`.
|
||||
|
||||
Important to be noted: if the chromium instance crashes when you run it, you might need to
|
||||
use `--no-sandbox` to make it work:
|
||||
|
||||
```bash
|
||||
$ ./x.py test tests/rustdoc-gui --stage 1 --test-args --no-sandbox
|
||||
```
|
||||
|
||||
[browser-ui-test]: https://github.com/GuillaumeGomez/browser-UI-test/
|
||||
[puppeteer]: https://pptr.dev/
|
||||
|
19
tests/rustdoc-ui/cfg-boolean-literal.rs
Normal file
19
tests/rustdoc-ui/cfg-boolean-literal.rs
Normal file
@ -0,0 +1,19 @@
|
||||
//@ check-pass
|
||||
|
||||
#![feature(cfg_boolean_literals)]
|
||||
#![feature(doc_cfg)]
|
||||
|
||||
#[doc(cfg(false))]
|
||||
pub fn foo() {}
|
||||
|
||||
#[doc(cfg(true))]
|
||||
pub fn bar() {}
|
||||
|
||||
#[doc(cfg(any(true)))]
|
||||
pub fn zoo() {}
|
||||
|
||||
#[doc(cfg(all(true)))]
|
||||
pub fn toy() {}
|
||||
|
||||
#[doc(cfg(not(true)))]
|
||||
pub fn nay() {}
|
@ -44,7 +44,7 @@ LL | p as usize;
|
||||
|
|
||||
= help: cast through a thin pointer first
|
||||
|
||||
error[E0607]: cannot cast thin pointer `*const i32` to fat pointer `*const [i32]`
|
||||
error[E0607]: cannot cast thin pointer `*const i32` to wide pointer `*const [i32]`
|
||||
--> $DIR/fat-ptr-cast.rs:19:5
|
||||
|
|
||||
LL | q as *const [i32];
|
||||
|
19
tests/ui/cfg/raw-true-false.rs
Normal file
19
tests/ui/cfg/raw-true-false.rs
Normal file
@ -0,0 +1,19 @@
|
||||
//@ check-pass
|
||||
//@ compile-flags: --cfg false --check-cfg=cfg(r#false)
|
||||
|
||||
#![deny(warnings)]
|
||||
|
||||
#[expect(unexpected_cfgs)]
|
||||
mod a {
|
||||
#[cfg(r#true)]
|
||||
pub fn foo() {}
|
||||
}
|
||||
|
||||
mod b {
|
||||
#[cfg(r#false)]
|
||||
pub fn bar() {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
b::bar()
|
||||
}
|
30
tests/ui/cfg/true-false.rs
Normal file
30
tests/ui/cfg/true-false.rs
Normal file
@ -0,0 +1,30 @@
|
||||
//@ run-pass
|
||||
|
||||
#![feature(link_cfg)]
|
||||
#![feature(cfg_boolean_literals)]
|
||||
|
||||
#[cfg(true)]
|
||||
fn foo() -> bool {
|
||||
cfg!(true)
|
||||
}
|
||||
|
||||
#[cfg(false)]
|
||||
fn foo() -> bool {
|
||||
cfg!(false)
|
||||
}
|
||||
|
||||
#[cfg_attr(true, cfg(false))]
|
||||
fn foo() {}
|
||||
|
||||
#[link(name = "foo", cfg(false))]
|
||||
extern "C" {}
|
||||
|
||||
fn main() {
|
||||
assert!(foo());
|
||||
assert!(cfg!(true));
|
||||
assert!(!cfg!(false));
|
||||
assert!(cfg!(not(false)));
|
||||
assert!(cfg!(all(true)));
|
||||
assert!(cfg!(any(true)));
|
||||
assert!(!cfg!(not(true)));
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
error[E0607]: cannot cast thin pointer `*const [i64; 0]` to fat pointer `*const [u8]`
|
||||
error[E0607]: cannot cast thin pointer `*const [i64; 0]` to wide pointer `*const [u8]`
|
||||
--> $DIR/slice_elem_ty_mismatch_in_unsizing_cast.rs:1:31
|
||||
|
|
||||
LL | const FOO: &str = unsafe { &*(1_usize as *const [i64; 0] as *const [u8] as *const str) };
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
|
||||
error[E0607]: cannot cast thin pointer `*const u8` to wide pointer `*const [u8]`
|
||||
--> $DIR/E0607.rs:3:5
|
||||
|
|
||||
LL | v as *const [u8];
|
||||
|
@ -81,7 +81,7 @@ help: dereference the expression
|
||||
LL | let y: u32 = *x as u32;
|
||||
| +
|
||||
|
||||
error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
|
||||
error[E0607]: cannot cast thin pointer `*const u8` to wide pointer `*const [u8]`
|
||||
--> $DIR/error-festival.rs:41:5
|
||||
|
|
||||
LL | v as *const [u8];
|
||||
|
10
tests/ui/feature-gates/feature-gate-cfg-boolean-literals.rs
Normal file
10
tests/ui/feature-gates/feature-gate-cfg-boolean-literals.rs
Normal file
@ -0,0 +1,10 @@
|
||||
#[cfg(true)] //~ ERROR `cfg(true)` is experimental
|
||||
fn foo() {}
|
||||
|
||||
#[cfg_attr(true, cfg(false))] //~ ERROR `cfg(true)` is experimental
|
||||
//~^ ERROR `cfg(false)` is experimental
|
||||
fn foo() {}
|
||||
|
||||
fn main() {
|
||||
cfg!(false); //~ ERROR `cfg(false)` is experimental
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
error[E0658]: `cfg(true)` is experimental and subject to change
|
||||
--> $DIR/feature-gate-cfg-boolean-literals.rs:1:7
|
||||
|
|
||||
LL | #[cfg(true)]
|
||||
| ^^^^
|
||||
|
|
||||
= note: see issue #131204 <https://github.com/rust-lang/rust/issues/131204> for more information
|
||||
= help: add `#![feature(cfg_boolean_literals)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: `cfg(true)` is experimental and subject to change
|
||||
--> $DIR/feature-gate-cfg-boolean-literals.rs:4:12
|
||||
|
|
||||
LL | #[cfg_attr(true, cfg(false))]
|
||||
| ^^^^
|
||||
|
|
||||
= note: see issue #131204 <https://github.com/rust-lang/rust/issues/131204> for more information
|
||||
= help: add `#![feature(cfg_boolean_literals)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: `cfg(false)` is experimental and subject to change
|
||||
--> $DIR/feature-gate-cfg-boolean-literals.rs:4:22
|
||||
|
|
||||
LL | #[cfg_attr(true, cfg(false))]
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #131204 <https://github.com/rust-lang/rust/issues/131204> for more information
|
||||
= help: add `#![feature(cfg_boolean_literals)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: `cfg(false)` is experimental and subject to change
|
||||
--> $DIR/feature-gate-cfg-boolean-literals.rs:9:10
|
||||
|
|
||||
LL | cfg!(false);
|
||||
| ^^^^^
|
||||
|
|
||||
= note: see issue #131204 <https://github.com/rust-lang/rust/issues/131204> for more information
|
||||
= help: add `#![feature(cfg_boolean_literals)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -1,6 +1,6 @@
|
||||
fn cast_thin_to_fat(x: *const ()) {
|
||||
x as *const [u8];
|
||||
//~^ ERROR: cannot cast thin pointer `*const ()` to fat pointer `*const [u8]`
|
||||
//~^ ERROR: cannot cast thin pointer `*const ()` to wide pointer `*const [u8]`
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0607]: cannot cast thin pointer `*const ()` to fat pointer `*const [u8]`
|
||||
error[E0607]: cannot cast thin pointer `*const ()` to wide pointer `*const [u8]`
|
||||
--> $DIR/issue-31511.rs:2:5
|
||||
|
|
||||
LL | x as *const [u8];
|
||||
|
@ -1,6 +1,6 @@
|
||||
fn main() {
|
||||
cfg!(); //~ ERROR macro requires a cfg-pattern
|
||||
cfg!(123); //~ ERROR expected identifier
|
||||
cfg!(123); //~ ERROR literal in `cfg` predicate value must be a boolean
|
||||
cfg!(foo = 123); //~ ERROR literal in `cfg` predicate value must be a string
|
||||
cfg!(foo, bar); //~ ERROR expected 1 cfg-pattern
|
||||
}
|
||||
|
@ -6,11 +6,11 @@ LL | cfg!();
|
||||
|
|
||||
= note: this error originates in the macro `cfg` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: expected identifier, found `123`
|
||||
error[E0565]: literal in `cfg` predicate value must be a boolean
|
||||
--> $DIR/cfg.rs:3:10
|
||||
|
|
||||
LL | cfg!(123);
|
||||
| ^^^ expected identifier
|
||||
| ^^^
|
||||
|
||||
error[E0565]: literal in `cfg` predicate value must be a string
|
||||
--> $DIR/cfg.rs:4:16
|
||||
|
@ -158,7 +158,7 @@ LL | let _ = 42usize as *const [u8];
|
||||
| |
|
||||
| consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts`
|
||||
|
||||
error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
|
||||
error[E0607]: cannot cast thin pointer `*const u8` to wide pointer `*const [u8]`
|
||||
--> $DIR/cast-rfc0401.rs:52:13
|
||||
|
|
||||
LL | let _ = v as *const [u8];
|
||||
|
@ -925,6 +925,7 @@ users_on_vacation = [
|
||||
"jhpratt",
|
||||
"jyn514",
|
||||
"oli-obk",
|
||||
"jieyouxu",
|
||||
]
|
||||
|
||||
[assign.adhoc_groups]
|
||||
|
Loading…
Reference in New Issue
Block a user