mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +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`.
|
/// Returns the `MetaItem` if `self` is a `NestedMetaItem::MetaItem`.
|
||||||
pub fn meta_item(&self) -> Option<&MetaItem> {
|
pub fn meta_item(&self) -> Option<&MetaItem> {
|
||||||
match self {
|
match self {
|
||||||
|
@ -107,6 +107,8 @@ attr_unknown_version_literal =
|
|||||||
attr_unstable_cfg_target_compact =
|
attr_unstable_cfg_target_compact =
|
||||||
compact `cfg(target(..))` is experimental and subject to change
|
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 =
|
attr_unsupported_literal_cfg_string =
|
||||||
literal in `cfg` predicate value must be a string
|
literal in `cfg` predicate value must be a string
|
||||||
attr_unsupported_literal_deprecated_kv_pair =
|
attr_unsupported_literal_deprecated_kv_pair =
|
||||||
|
@ -18,7 +18,7 @@ use rustc_session::parse::feature_err;
|
|||||||
use rustc_session::{RustcVersion, Session};
|
use rustc_session::{RustcVersion, Session};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_span::hygiene::Transparency;
|
use rustc_span::hygiene::Transparency;
|
||||||
use rustc_span::symbol::{Symbol, sym};
|
use rustc_span::symbol::{Symbol, kw, sym};
|
||||||
|
|
||||||
use crate::fluent_generated;
|
use crate::fluent_generated;
|
||||||
use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
|
use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
|
||||||
@ -36,6 +36,7 @@ pub fn is_builtin_attr(attr: &Attribute) -> bool {
|
|||||||
pub(crate) enum UnsupportedLiteralReason {
|
pub(crate) enum UnsupportedLiteralReason {
|
||||||
Generic,
|
Generic,
|
||||||
CfgString,
|
CfgString,
|
||||||
|
CfgBoolean,
|
||||||
DeprecatedString,
|
DeprecatedString,
|
||||||
DeprecatedKvPair,
|
DeprecatedKvPair,
|
||||||
}
|
}
|
||||||
@ -533,7 +534,7 @@ pub struct Condition {
|
|||||||
|
|
||||||
/// Tests if a cfg-pattern matches the cfg set
|
/// Tests if a cfg-pattern matches the cfg set
|
||||||
pub fn cfg_matches(
|
pub fn cfg_matches(
|
||||||
cfg: &ast::MetaItem,
|
cfg: &ast::NestedMetaItem,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
lint_node_id: NodeId,
|
lint_node_id: NodeId,
|
||||||
features: Option<&Features>,
|
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 a cfg-like condition (with `any` and `all`), using `eval` to
|
||||||
/// evaluate individual items.
|
/// evaluate individual items.
|
||||||
pub fn eval_condition(
|
pub fn eval_condition(
|
||||||
cfg: &ast::MetaItem,
|
cfg: &ast::NestedMetaItem,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
features: Option<&Features>,
|
features: Option<&Features>,
|
||||||
eval: &mut impl FnMut(Condition) -> bool,
|
eval: &mut impl FnMut(Condition) -> bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let dcx = sess.dcx();
|
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 {
|
match &cfg.kind {
|
||||||
ast::MetaItemKind::List(mis) if cfg.name_or_empty() == sym::version => {
|
ast::MetaItemKind::List(mis) if cfg.name_or_empty() == sym::version => {
|
||||||
try_gate_cfg(sym::version, cfg.span, sess, features);
|
try_gate_cfg(sym::version, cfg.span, sess, features);
|
||||||
@ -645,7 +677,7 @@ pub fn eval_condition(
|
|||||||
}
|
}
|
||||||
ast::MetaItemKind::List(mis) => {
|
ast::MetaItemKind::List(mis) => {
|
||||||
for mi in mis.iter() {
|
for mi in mis.iter() {
|
||||||
if !mi.is_meta_item() {
|
if mi.meta_item_or_bool().is_none() {
|
||||||
dcx.emit_err(session_diagnostics::UnsupportedLiteral {
|
dcx.emit_err(session_diagnostics::UnsupportedLiteral {
|
||||||
span: mi.span(),
|
span: mi.span(),
|
||||||
reason: UnsupportedLiteralReason::Generic,
|
reason: UnsupportedLiteralReason::Generic,
|
||||||
@ -663,23 +695,19 @@ pub fn eval_condition(
|
|||||||
.iter()
|
.iter()
|
||||||
// We don't use any() here, because we want to evaluate all cfg condition
|
// We don't use any() here, because we want to evaluate all cfg condition
|
||||||
// as eval_condition can (and does) extra checks
|
// as eval_condition can (and does) extra checks
|
||||||
.fold(false, |res, mi| {
|
.fold(false, |res, mi| res | eval_condition(mi, sess, features, eval)),
|
||||||
res | eval_condition(mi.meta_item().unwrap(), sess, features, eval)
|
|
||||||
}),
|
|
||||||
sym::all => mis
|
sym::all => mis
|
||||||
.iter()
|
.iter()
|
||||||
// We don't use all() here, because we want to evaluate all cfg condition
|
// We don't use all() here, because we want to evaluate all cfg condition
|
||||||
// as eval_condition can (and does) extra checks
|
// as eval_condition can (and does) extra checks
|
||||||
.fold(true, |res, mi| {
|
.fold(true, |res, mi| res & eval_condition(mi, sess, features, eval)),
|
||||||
res & eval_condition(mi.meta_item().unwrap(), sess, features, eval)
|
|
||||||
}),
|
|
||||||
sym::not => {
|
sym::not => {
|
||||||
let [mi] = mis.as_slice() else {
|
let [mi] = mis.as_slice() else {
|
||||||
dcx.emit_err(session_diagnostics::ExpectedOneCfgPattern { span: cfg.span });
|
dcx.emit_err(session_diagnostics::ExpectedOneCfgPattern { span: cfg.span });
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
!eval_condition(mi.meta_item().unwrap(), sess, features, eval)
|
!eval_condition(mi, sess, features, eval)
|
||||||
}
|
}
|
||||||
sym::target => {
|
sym::target => {
|
||||||
if let Some(features) = features
|
if let Some(features) = features
|
||||||
@ -700,7 +728,12 @@ pub fn eval_condition(
|
|||||||
seg.ident.name = Symbol::intern(&format!("target_{}", seg.ident.name));
|
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 {
|
let mut diag = Diag::new(dcx, level, match self.reason {
|
||||||
UnsupportedLiteralReason::Generic => fluent::attr_unsupported_literal_generic,
|
UnsupportedLiteralReason::Generic => fluent::attr_unsupported_literal_generic,
|
||||||
UnsupportedLiteralReason::CfgString => fluent::attr_unsupported_literal_cfg_string,
|
UnsupportedLiteralReason::CfgString => fluent::attr_unsupported_literal_cfg_string,
|
||||||
|
UnsupportedLiteralReason::CfgBoolean => fluent::attr_unsupported_literal_cfg_boolean,
|
||||||
UnsupportedLiteralReason::DeprecatedString => {
|
UnsupportedLiteralReason::DeprecatedString => {
|
||||||
fluent::attr_unsupported_literal_deprecated_string
|
fluent::attr_unsupported_literal_deprecated_string
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ use rustc_ast::token;
|
|||||||
use rustc_ast::tokenstream::TokenStream;
|
use rustc_ast::tokenstream::TokenStream;
|
||||||
use rustc_errors::PResult;
|
use rustc_errors::PResult;
|
||||||
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
|
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
|
||||||
use rustc_parse::parser::attr::AllowLeadingUnsafe;
|
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use {rustc_ast as ast, rustc_attr as attr};
|
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);
|
let mut p = cx.new_parser_from_tts(tts);
|
||||||
|
|
||||||
if p.token == token::Eof {
|
if p.token == token::Eof {
|
||||||
return Err(cx.dcx().create_err(errors::RequiresCfgPattern { span }));
|
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);
|
let _ = p.eat(&token::Comma);
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ fn main() {
|
|||||||
|
|
||||||
foo(I64X2([0, 0]));
|
foo(I64X2([0, 0]));
|
||||||
|
|
||||||
transmute_fat_pointer();
|
transmute_wide_pointer();
|
||||||
|
|
||||||
rust_call_abi();
|
rust_call_abi();
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ type TwoPtrs = i64;
|
|||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
type TwoPtrs = i128;
|
type TwoPtrs = i128;
|
||||||
|
|
||||||
fn transmute_fat_pointer() -> TwoPtrs {
|
fn transmute_wide_pointer() -> TwoPtrs {
|
||||||
unsafe { transmute::<_, TwoPtrs>("true !") }
|
unsafe { transmute::<_, TwoPtrs>("true !") }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -713,17 +713,17 @@ fn codegen_stmt<'tcx>(
|
|||||||
let from_ty = operand.layout().ty;
|
let from_ty = operand.layout().ty;
|
||||||
let to_ty = fx.monomorphize(to_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)
|
ty.builtin_deref(true)
|
||||||
.is_some_and(|pointee_ty| has_ptr_meta(fx.tcx, pointee_ty))
|
.is_some_and(|pointee_ty| has_ptr_meta(fx.tcx, pointee_ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_fat_ptr(fx, from_ty) {
|
if is_wide_ptr(fx, from_ty) {
|
||||||
if is_fat_ptr(fx, to_ty) {
|
if is_wide_ptr(fx, to_ty) {
|
||||||
// fat-ptr -> fat-ptr
|
// wide-ptr -> wide-ptr
|
||||||
lval.write_cvalue(fx, operand.cast_pointer_to(dest_layout));
|
lval.write_cvalue(fx, operand.cast_pointer_to(dest_layout));
|
||||||
} else {
|
} else {
|
||||||
// fat-ptr -> thin-ptr
|
// wide-ptr -> thin-ptr
|
||||||
let (ptr, _extra) = operand.load_scalar_pair(fx);
|
let (ptr, _extra) = operand.load_scalar_pair(fx);
|
||||||
lval.write_cvalue(fx, CValue::by_val(ptr, dest_layout))
|
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 {
|
pub(crate) fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||||
if ty.is_sized(tcx, ParamEnv::reveal_all()) {
|
if ty.is_sized(tcx, ParamEnv::reveal_all()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -139,7 +139,7 @@ impl DebugContext {
|
|||||||
|
|
||||||
pointer_type_id
|
pointer_type_id
|
||||||
} else {
|
} else {
|
||||||
// FIXME implement debuginfo for fat pointers
|
// FIXME implement debuginfo for wide pointers
|
||||||
self.placeholder_for_type(tcx, type_dbg, ptr_type)
|
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| {
|
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
|
||||||
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
||||||
});
|
});
|
||||||
require!(metadata.is_unit(), InvalidMonomorphization::CastFatPointer {
|
require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
|
||||||
span,
|
span,
|
||||||
name,
|
name,
|
||||||
ty: in_elem
|
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| {
|
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
|
||||||
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
||||||
});
|
});
|
||||||
require!(metadata.is_unit(), InvalidMonomorphization::CastFatPointer {
|
require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
|
||||||
span,
|
span,
|
||||||
name,
|
name,
|
||||||
ty: out_elem
|
ty: out_elem
|
||||||
|
@ -207,7 +207,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
|
|||||||
// layout.
|
// layout.
|
||||||
if let Abi::Scalar(ref scalar) = self.abi {
|
if let Abi::Scalar(ref scalar) = self.abi {
|
||||||
// Use a different cache for scalars because pointers to DSTs
|
// 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) {
|
if let Some(&ty) = cx.scalar_types.borrow().get(&self.ty) {
|
||||||
return ty;
|
return ty;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue};
|
|||||||
use rustc_codegen_ssa::traits::*;
|
use rustc_codegen_ssa::traits::*;
|
||||||
use rustc_middle::ty::Ty;
|
use rustc_middle::ty::Ty;
|
||||||
use rustc_middle::ty::layout::LayoutOf;
|
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_middle::{bug, ty};
|
||||||
use rustc_session::config;
|
use rustc_session::config;
|
||||||
pub(crate) use rustc_target::abi::call::*;
|
pub(crate) use rustc_target::abi::call::*;
|
||||||
|
@ -34,7 +34,7 @@ use super::utils::{
|
|||||||
};
|
};
|
||||||
use crate::common::CodegenCx;
|
use crate::common::CodegenCx;
|
||||||
use crate::debuginfo::metadata::type_map::build_type_with_children;
|
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::{
|
use crate::llvm::debuginfo::{
|
||||||
DIDescriptor, DIFile, DIFlags, DILexicalBlock, DIScope, DIType, DebugEmissionKind,
|
DIDescriptor, DIFile, DIFlags, DILexicalBlock, DIScope, DIType, DebugEmissionKind,
|
||||||
DebugNameTableKind,
|
DebugNameTableKind,
|
||||||
@ -161,7 +161,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
|||||||
unique_type_id: UniqueTypeId<'tcx>,
|
unique_type_id: UniqueTypeId<'tcx>,
|
||||||
) -> DINodeCreationResult<'ll> {
|
) -> DINodeCreationResult<'ll> {
|
||||||
// The debuginfo generated by this function is only valid if `ptr_type` is really just
|
// 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!(
|
assert_eq!(
|
||||||
cx.size_and_align_of(ptr_type),
|
cx.size_and_align_of(ptr_type),
|
||||||
cx.size_and_align_of(Ty::new_mut_ptr(cx.tcx, pointee_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 data_layout = &cx.tcx.data_layout;
|
||||||
let ptr_type_debuginfo_name = compute_debuginfo_type_name(cx.tcx, ptr_type, true);
|
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 => {
|
None => {
|
||||||
// This is a thin pointer. Create a regular pointer type and give it the correct name.
|
// This is a thin pointer. Create a regular pointer type and give it the correct name.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -197,7 +197,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
|||||||
|
|
||||||
DINodeCreationResult { di_node, already_stored_in_typemap: false }
|
DINodeCreationResult { di_node, already_stored_in_typemap: false }
|
||||||
}
|
}
|
||||||
Some(fat_pointer_kind) => {
|
Some(wide_pointer_kind) => {
|
||||||
type_map::build_type_with_children(
|
type_map::build_type_with_children(
|
||||||
cx,
|
cx,
|
||||||
type_map::stub(
|
type_map::stub(
|
||||||
@ -210,7 +210,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
|||||||
DIFlags::FlagZero,
|
DIFlags::FlagZero,
|
||||||
),
|
),
|
||||||
|cx, owner| {
|
|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
|
// type layout and instead use the layout of the raw pointer inside
|
||||||
// of it.
|
// of it.
|
||||||
// The proper way to handle this is to not treat Box as a pointer
|
// 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 layout = cx.layout_of(layout_type);
|
||||||
let addr_field = layout.field(cx, abi::FAT_PTR_ADDR);
|
let addr_field = layout.field(cx, abi::WIDE_PTR_ADDR);
|
||||||
let extra_field = layout.field(cx, abi::FAT_PTR_EXTRA);
|
let extra_field = layout.field(cx, abi::WIDE_PTR_EXTRA);
|
||||||
|
|
||||||
let (addr_field_name, extra_field_name) = match fat_pointer_kind {
|
let (addr_field_name, extra_field_name) = match wide_pointer_kind {
|
||||||
FatPtrKind::Dyn => ("pointer", "vtable"),
|
WidePtrKind::Dyn => ("pointer", "vtable"),
|
||||||
FatPtrKind::Slice => ("data_ptr", "length"),
|
WidePtrKind::Slice => ("data_ptr", "length"),
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(abi::FAT_PTR_ADDR, 0);
|
assert_eq!(abi::WIDE_PTR_ADDR, 0);
|
||||||
assert_eq!(abi::FAT_PTR_EXTRA, 1);
|
assert_eq!(abi::WIDE_PTR_EXTRA, 1);
|
||||||
|
|
||||||
// The data pointer type is a regular, thin pointer, regardless of whether this
|
// The data pointer type is a regular, thin pointer, regardless of whether this
|
||||||
// is a slice or a trait object.
|
// is a slice or a trait object.
|
||||||
@ -258,7 +258,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
|||||||
owner,
|
owner,
|
||||||
addr_field_name,
|
addr_field_name,
|
||||||
(addr_field.size, addr_field.align.abi),
|
(addr_field.size, addr_field.align.abi),
|
||||||
layout.fields.offset(abi::FAT_PTR_ADDR),
|
layout.fields.offset(abi::WIDE_PTR_ADDR),
|
||||||
DIFlags::FlagZero,
|
DIFlags::FlagZero,
|
||||||
data_ptr_type_di_node,
|
data_ptr_type_di_node,
|
||||||
),
|
),
|
||||||
@ -267,7 +267,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
|||||||
owner,
|
owner,
|
||||||
extra_field_name,
|
extra_field_name,
|
||||||
(extra_field.size, extra_field.align.abi),
|
(extra_field.size, extra_field.align.abi),
|
||||||
layout.fields.offset(abi::FAT_PTR_EXTRA),
|
layout.fields.offset(abi::WIDE_PTR_EXTRA),
|
||||||
DIFlags::FlagZero,
|
DIFlags::FlagZero,
|
||||||
type_di_node(cx, extra_field.ty),
|
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
|
/// 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
|
/// (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]`.
|
/// debuginfo of `&[T]`.
|
||||||
///
|
///
|
||||||
/// It would be preferable and more accurate if we emitted a DIArray 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)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub(crate) enum FatPtrKind {
|
pub(crate) enum WidePtrKind {
|
||||||
Slice,
|
Slice,
|
||||||
Dyn,
|
Dyn,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines if `pointee_ty` is slice-like or trait-object-like, i.e.
|
/// 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 the second field of the wide pointer is a length or a vtable-pointer.
|
||||||
/// If `pointee_ty` does not require a fat pointer (because it is Sized) then
|
/// If `pointee_ty` does not require a wide pointer (because it is Sized) then
|
||||||
/// the function returns `None`.
|
/// the function returns `None`.
|
||||||
pub(crate) fn fat_pointer_kind<'ll, 'tcx>(
|
pub(crate) fn wide_pointer_kind<'ll, 'tcx>(
|
||||||
cx: &CodegenCx<'ll, 'tcx>,
|
cx: &CodegenCx<'ll, 'tcx>,
|
||||||
pointee_ty: Ty<'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 pointee_tail_ty = cx.tcx.struct_tail_for_codegen(pointee_ty, cx.param_env());
|
||||||
let layout = cx.layout_of(pointee_tail_ty);
|
let layout = cx.layout_of(pointee_tail_ty);
|
||||||
trace!(
|
trace!(
|
||||||
"fat_pointer_kind: {:?} has layout {:?} (is_unsized? {})",
|
"wide_pointer_kind: {:?} has layout {:?} (is_unsized? {})",
|
||||||
pointee_tail_ty,
|
pointee_tail_ty,
|
||||||
layout,
|
layout,
|
||||||
layout.is_unsized()
|
layout.is_unsized()
|
||||||
@ -76,8 +76,8 @@ pub(crate) fn fat_pointer_kind<'ll, 'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
match *pointee_tail_ty.kind() {
|
match *pointee_tail_ty.kind() {
|
||||||
ty::Str | ty::Slice(_) => Some(FatPtrKind::Slice),
|
ty::Str | ty::Slice(_) => Some(WidePtrKind::Slice),
|
||||||
ty::Dynamic(..) => Some(FatPtrKind::Dyn),
|
ty::Dynamic(..) => Some(WidePtrKind::Dyn),
|
||||||
ty::Foreign(_) => {
|
ty::Foreign(_) => {
|
||||||
// Assert that pointers to foreign types really are thin:
|
// Assert that pointers to foreign types really are thin:
|
||||||
assert_eq!(
|
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
|
// For all other pointee types we should already have returned None
|
||||||
// at the beginning of the function.
|
// at the beginning of the function.
|
||||||
panic!(
|
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| {
|
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
|
||||||
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
||||||
});
|
});
|
||||||
require!(metadata.is_unit(), InvalidMonomorphization::CastFatPointer {
|
require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
|
||||||
span,
|
span,
|
||||||
name,
|
name,
|
||||||
ty: in_elem
|
ty: in_elem
|
||||||
@ -2200,7 +2200,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||||||
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
|
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
|
||||||
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
||||||
});
|
});
|
||||||
require!(metadata.is_unit(), InvalidMonomorphization::CastFatPointer {
|
require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
|
||||||
span,
|
span,
|
||||||
name,
|
name,
|
||||||
ty: out_elem
|
ty: out_elem
|
||||||
|
@ -199,7 +199,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
|||||||
// layout.
|
// layout.
|
||||||
if let Abi::Scalar(scalar) = self.abi {
|
if let Abi::Scalar(scalar) = self.abi {
|
||||||
// Use a different cache for scalars because pointers to DSTs
|
// 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) {
|
if let Some(&llty) = cx.scalar_lltypes.borrow().get(&self.ty) {
|
||||||
return llty;
|
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_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}`
|
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>,
|
ret_ty: Ty<'tcx>,
|
||||||
},
|
},
|
||||||
|
|
||||||
#[diag(codegen_ssa_invalid_monomorphization_cast_fat_pointer, code = E0511)]
|
#[diag(codegen_ssa_invalid_monomorphization_cast_wide_pointer, code = E0511)]
|
||||||
CastFatPointer {
|
CastWidePointer {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
span: Span,
|
span: Span,
|
||||||
name: Symbol,
|
name: Symbol,
|
||||||
|
@ -156,7 +156,7 @@ pub struct NativeLib {
|
|||||||
pub kind: NativeLibKind,
|
pub kind: NativeLibKind,
|
||||||
pub name: Symbol,
|
pub name: Symbol,
|
||||||
pub filename: Option<Symbol>,
|
pub filename: Option<Symbol>,
|
||||||
pub cfg: Option<ast::MetaItem>,
|
pub cfg: Option<ast::NestedMetaItem>,
|
||||||
pub verbatim: bool,
|
pub verbatim: bool,
|
||||||
pub dll_imports: Vec<cstore::DllImport>,
|
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> {
|
enum LocalRef<'tcx, V> {
|
||||||
Place(PlaceRef<'tcx, V>),
|
Place(PlaceRef<'tcx, V>),
|
||||||
/// `UnsizedPlace(p)`: `p` itself is a thin pointer (indirect place).
|
/// `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
|
/// 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>),
|
UnsizedPlace(PlaceRef<'tcx, V>),
|
||||||
/// The backend [`OperandValue`] has already been generated.
|
/// The backend [`OperandValue`] has already been generated.
|
||||||
Operand(OperandRef<'tcx, V>),
|
Operand(OperandRef<'tcx, V>),
|
||||||
@ -429,7 +429,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||||||
// Unsized indirect qrguments
|
// Unsized indirect qrguments
|
||||||
PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
|
PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
|
||||||
// As the storage for the indirect argument lives during
|
// 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);
|
let llarg = bx.get_param(llarg_idx);
|
||||||
llarg_idx += 1;
|
llarg_idx += 1;
|
||||||
let llextra = bx.get_param(llarg_idx);
|
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,
|
/// The backend value in this variant must be the *immediate* backend type,
|
||||||
/// as returned by [`LayoutTypeCodegenMethods::immediate_backend_type`].
|
/// as returned by [`LayoutTypeCodegenMethods::immediate_backend_type`].
|
||||||
Immediate(V),
|
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
|
/// An `OperandValue` *must* be this variant for any type for which
|
||||||
/// [`LayoutTypeCodegenMethods::is_backend_scalar_pair`] returns `true`.
|
/// [`LayoutTypeCodegenMethods::is_backend_scalar_pair`] returns `true`.
|
||||||
|
@ -38,10 +38,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
ref source,
|
ref source,
|
||||||
_,
|
_,
|
||||||
) => {
|
) => {
|
||||||
// The destination necessarily contains a fat pointer, so if
|
// The destination necessarily contains a wide pointer, so if
|
||||||
// it's a scalar pair, it's a fat pointer or newtype thereof.
|
// it's a scalar pair, it's a wide pointer or newtype thereof.
|
||||||
if bx.cx().is_backend_scalar_pair(dest.layout) {
|
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.
|
// use the operand path.
|
||||||
let temp = self.codegen_rvalue_operand(bx, rvalue);
|
let temp = self.codegen_rvalue_operand(bx, rvalue);
|
||||||
temp.val.store(bx, dest);
|
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) {
|
if bx.cx().is_backend_scalar_pair(cast) {
|
||||||
OperandValue::Pair(data_ptr, meta)
|
OperandValue::Pair(data_ptr, meta)
|
||||||
} else {
|
} 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)
|
OperandValue::Immediate(data_ptr)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -622,7 +622,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
(
|
(
|
||||||
OperandValue::Pair(lhs_addr, lhs_extra),
|
OperandValue::Pair(lhs_addr, lhs_extra),
|
||||||
OperandValue::Pair(rhs_addr, rhs_extra),
|
OperandValue::Pair(rhs_addr, rhs_extra),
|
||||||
) => self.codegen_fat_ptr_binop(
|
) => self.codegen_wide_ptr_binop(
|
||||||
bx,
|
bx,
|
||||||
op,
|
op,
|
||||||
lhs_addr,
|
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,
|
&mut self,
|
||||||
bx: &mut Bx,
|
bx: &mut Bx,
|
||||||
op: mir::BinOp,
|
op: mir::BinOp,
|
||||||
@ -1021,7 +1021,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
bx.or(lhs, rhs)
|
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>> {
|
) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
|
||||||
assert!(src.layout.ty.is_any_ptr());
|
assert!(src.layout.ty.is_any_ptr());
|
||||||
assert!(cast_to.ty.is_unsafe_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 {
|
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));
|
return interp_ok(ImmTy::from_immediate(**src, cast_to));
|
||||||
} else {
|
} 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!(src.layout.size, 2 * self.pointer_size());
|
||||||
assert_eq!(cast_to.size, self.pointer_size());
|
assert_eq!(cast_to.size, self.pointer_size());
|
||||||
assert!(src.layout.ty.is_unsafe_ptr());
|
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:
|
Erroneous code example:
|
||||||
|
|
||||||
@ -7,18 +7,18 @@ let v = core::ptr::null::<u8>();
|
|||||||
v as *const [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
|
Thin pointers are "simple" pointers: they are purely a reference to a memory
|
||||||
address.
|
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
|
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,
|
behind some kind of pointer that contains additional information. For example,
|
||||||
slices and trait objects are DSTs. In the case of slices, the additional
|
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
|
For more information about type casts, take a look at the section of the
|
||||||
[The Rust Reference][1] on type cast expressions.
|
[The Rust Reference][1] on type cast expressions.
|
||||||
|
@ -5,7 +5,9 @@ use rustc_ast::token::{Delimiter, Token, TokenKind};
|
|||||||
use rustc_ast::tokenstream::{
|
use rustc_ast::tokenstream::{
|
||||||
AttrTokenStream, AttrTokenTree, LazyAttrTokenStream, Spacing, TokenTree,
|
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_attr as attr;
|
||||||
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
|
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
|
||||||
use rustc_feature::{
|
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;
|
let span = meta_item.span;
|
||||||
match meta_item.meta_item_list() {
|
match meta_item.meta_item_list() {
|
||||||
None => {
|
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() });
|
sess.dcx().emit_err(InvalidCfg::MultiplePredicates { span: l.span() });
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
Some([single]) => match single.meta_item() {
|
Some([single]) => match single.meta_item_or_bool() {
|
||||||
Some(meta_item) => Some(meta_item),
|
Some(meta_item) => Some(meta_item),
|
||||||
None => {
|
None => {
|
||||||
sess.dcx().emit_err(InvalidCfg::PredicateLiteral { span: single.span() });
|
sess.dcx().emit_err(InvalidCfg::PredicateLiteral { span: single.span() });
|
||||||
|
@ -371,6 +371,8 @@ declare_features! (
|
|||||||
(unstable, async_for_loop, "1.77.0", Some(118898)),
|
(unstable, async_for_loop, "1.77.0", Some(118898)),
|
||||||
/// Allows using C-variadics.
|
/// Allows using C-variadics.
|
||||||
(unstable, c_variadic, "1.34.0", Some(44930)),
|
(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.
|
/// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour.
|
||||||
(unstable, cfg_overflow_checks, "1.71.0", Some(111466)),
|
(unstable, cfg_overflow_checks, "1.71.0", Some(111466)),
|
||||||
/// Provides the relocation model information as cfg entry
|
/// 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"
|
// 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
|
// These are scalar types which directly match a "machine" type
|
||||||
// Yes: Integers, floats, "thin" pointers
|
// Yes: Integers, floats, "thin" pointers
|
||||||
// No: char, "fat" pointers, compound types
|
// No: char, "wide" pointers, compound types
|
||||||
match element_ty.kind() {
|
match element_ty.kind() {
|
||||||
ty::Param(_) => (), // pass struct<T>([T; 4]) through, let monomorphization catch errors
|
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
|
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,
|
// Here `U = [i32; 3]` and `V = [i32]`. At runtime,
|
||||||
// when this coercion occurs, we would be changing the
|
// when this coercion occurs, we would be changing the
|
||||||
// field `ptr` from a thin pointer of type `*mut [i32;
|
// 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
|
// extra data `3`). **The purpose of this check is to
|
||||||
// make sure that we know how to do this conversion.**
|
// 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_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
|
.teach_help = Thin pointers are "simple" pointers: they are purely a reference to a
|
||||||
memory address.
|
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
|
called DST). DST don't have a statically known size, therefore they can
|
||||||
only exist behind some kind of pointers that contain additional
|
only exist behind some kind of pointers that contain additional
|
||||||
information. Slices and trait objects are DSTs. In the case of slices,
|
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.
|
pointers.
|
||||||
|
|
||||||
For more information about casts, take a look at The Book:
|
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
|
/// 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.
|
/// kind.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, TypeVisitable, TypeFoldable)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, TypeVisitable, TypeFoldable)]
|
||||||
enum PointerKind<'tcx> {
|
enum PointerKind<'tcx> {
|
||||||
@ -162,7 +162,7 @@ enum CastError<'tcx> {
|
|||||||
src_kind: PointerKind<'tcx>,
|
src_kind: PointerKind<'tcx>,
|
||||||
dst_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,
|
SizedUnsizedCast,
|
||||||
IllegalCast,
|
IllegalCast,
|
||||||
NeedDeref,
|
NeedDeref,
|
||||||
@ -172,12 +172,12 @@ enum CastError<'tcx> {
|
|||||||
NonScalar,
|
NonScalar,
|
||||||
UnknownExprPtrKind,
|
UnknownExprPtrKind,
|
||||||
UnknownCastPtrKind,
|
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"
|
/// 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,
|
/// 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.
|
/// when we're typechecking a type parameter with a ?Sized bound.
|
||||||
IntToFatCast(Option<&'static str>),
|
IntToWideCast(Option<&'static str>),
|
||||||
ForeignNonExhaustiveAdt,
|
ForeignNonExhaustiveAdt,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -545,14 +545,14 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
CastError::SizedUnsizedCast => {
|
CastError::SizedUnsizedCast => {
|
||||||
fcx.dcx().emit_err(errors::CastThinPointerToFatPointer {
|
fcx.dcx().emit_err(errors::CastThinPointerToWidePointer {
|
||||||
span: self.span,
|
span: self.span,
|
||||||
expr_ty: self.expr_ty,
|
expr_ty: self.expr_ty,
|
||||||
cast_ty: fcx.ty_to_string(self.cast_ty),
|
cast_ty: fcx.ty_to_string(self.cast_ty),
|
||||||
teach: fcx.tcx.sess.teach(E0607),
|
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 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 cast_ty = fcx.resolve_vars_if_possible(self.cast_ty);
|
||||||
let expr_ty = fcx.ty_to_string(self.expr_ty);
|
let expr_ty = fcx.ty_to_string(self.expr_ty);
|
||||||
@ -861,7 +861,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||||||
return Ok(CastKind::PtrPtrCast);
|
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 {
|
let Some(src_kind) = src_kind else {
|
||||||
return Err(CastError::UnknownCastPtrKind);
|
return Err(CastError::UnknownCastPtrKind);
|
||||||
};
|
};
|
||||||
@ -1054,10 +1054,10 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||||||
match fcx.pointer_kind(m_cast.ty, self.span)? {
|
match fcx.pointer_kind(m_cast.ty, self.span)? {
|
||||||
None => Err(CastError::UnknownCastPtrKind),
|
None => Err(CastError::UnknownCastPtrKind),
|
||||||
Some(PointerKind::Thin) => Ok(CastKind::AddrPtrCast),
|
Some(PointerKind::Thin) => Ok(CastKind::AddrPtrCast),
|
||||||
Some(PointerKind::VTable(_)) => Err(CastError::IntToFatCast(Some("a vtable"))),
|
Some(PointerKind::VTable(_)) => Err(CastError::IntToWideCast(Some("a vtable"))),
|
||||||
Some(PointerKind::Length) => Err(CastError::IntToFatCast(Some("a length"))),
|
Some(PointerKind::Length) => Err(CastError::IntToWideCast(Some("a length"))),
|
||||||
Some(PointerKind::OfAlias(_) | PointerKind::OfParam(_)) => {
|
Some(PointerKind::OfAlias(_) | PointerKind::OfParam(_)) => {
|
||||||
Err(CastError::IntToFatCast(None))
|
Err(CastError::IntToWideCast(None))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -699,8 +699,8 @@ pub(crate) struct ReplaceWithName {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(hir_typeck_cast_thin_pointer_to_fat_pointer, code = E0607)]
|
#[diag(hir_typeck_cast_thin_pointer_to_wide_pointer, code = E0607)]
|
||||||
pub(crate) struct CastThinPointerToFatPointer<'tcx> {
|
pub(crate) struct CastThinPointerToWidePointer<'tcx> {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub expr_ty: Ty<'tcx>,
|
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
|
/// be checked higher up, as is the case with `&expr` and `box expr`), but
|
||||||
/// is useful in determining the concrete type.
|
/// 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:
|
/// like `&[isize]`. For example, consider the following statement:
|
||||||
///
|
///
|
||||||
/// let x: &[isize] = &[1, 2, 3];
|
/// let x: &[isize] = &[1, 2, 3];
|
||||||
|
@ -413,7 +413,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
ty::Ref(_, ty, _) | ty::RawPtr(ty, _) => {
|
ty::Ref(_, ty, _) | ty::RawPtr(ty, _) => {
|
||||||
if oprnd.is_syntactic_place_expr() {
|
if oprnd.is_syntactic_place_expr() {
|
||||||
// Places may legitimately have unsized types.
|
// 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.
|
// the last field of a struct can be unsized.
|
||||||
ExpectHasType(*ty)
|
ExpectHasType(*ty)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
use std::path::{Path, PathBuf};
|
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_attr as attr;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_middle::query::LocalCrate;
|
use rustc_middle::query::LocalCrate;
|
||||||
@ -304,7 +304,12 @@ impl<'tcx> Collector<'tcx> {
|
|||||||
sess.dcx().emit_err(errors::LinkCfgForm { span: item.span() });
|
sess.dcx().emit_err(errors::LinkCfgForm { span: item.span() });
|
||||||
continue;
|
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()
|
sess.dcx()
|
||||||
.emit_err(errors::LinkCfgSinglePredicate { span: item.span() });
|
.emit_err(errors::LinkCfgSinglePredicate { span: item.span() });
|
||||||
continue;
|
continue;
|
||||||
|
@ -25,10 +25,10 @@ pub enum PointerCoercion {
|
|||||||
ArrayToPointer,
|
ArrayToPointer,
|
||||||
|
|
||||||
/// Unsize a pointer/reference value, e.g., `&[T; n]` to
|
/// Unsize a pointer/reference value, e.g., `&[T; n]` to
|
||||||
/// `&[T]`. Note that the source could be a thin or fat pointer.
|
/// `&[T]`. Note that the source could be a thin or wide pointer.
|
||||||
/// This will do things like convert thin pointers to fat
|
/// This will do things like convert thin pointers to wide
|
||||||
/// pointers, or convert structs containing thin pointers to
|
/// 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
|
/// 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
|
/// done (in fact, we don't know that, because it might depend on
|
||||||
/// the precise type parameters). We just store the target
|
/// 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 trait object, this is the address of the box.
|
||||||
/// - For a slice, this is the base address.
|
/// - 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 trait object, this is the address of the vtable.
|
||||||
/// - For a slice, this is the length.
|
/// - 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.
|
/// 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.
|
/// that another SizeSkeleton is of equal size.
|
||||||
Generic(ty::Const<'tcx>),
|
Generic(ty::Const<'tcx>),
|
||||||
|
|
||||||
/// A potentially-fat pointer.
|
/// A potentially-wide pointer.
|
||||||
Pointer {
|
Pointer {
|
||||||
/// If true, this pointer is never null.
|
/// If true, this pointer is never null.
|
||||||
non_zero: bool,
|
non_zero: bool,
|
||||||
@ -785,11 +785,11 @@ where
|
|||||||
bug!("TyAndLayout::field({:?}): not applicable", this)
|
bug!("TyAndLayout::field({:?}): not applicable", this)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Potentially-fat pointers.
|
// Potentially-wide pointers.
|
||||||
ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => {
|
ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => {
|
||||||
assert!(i < this.fields.count());
|
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
|
// This provides information about, e.g., DST struct pointees
|
||||||
// (which may have no non-DST form), and will work as long
|
// (which may have no non-DST form), and will work as long
|
||||||
// as the `Abi` or `FieldsShape` is checked by users.
|
// 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())
|
.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.
|
/// or the struct tail if the metadata type cannot be determined.
|
||||||
pub fn ptr_metadata_ty_or_tail(
|
pub fn ptr_metadata_ty_or_tail(
|
||||||
self,
|
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.
|
/// Causes an ICE if the metadata type cannot be determined.
|
||||||
pub fn ptr_metadata_ty(
|
pub fn ptr_metadata_ty(
|
||||||
self,
|
self,
|
||||||
|
@ -1137,7 +1137,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||||||
(UnOp::PtrMetadata, Value::Aggregate(AggregateTy::RawPtr { .. }, _, fields)) => {
|
(UnOp::PtrMetadata, Value::Aggregate(AggregateTy::RawPtr { .. }, _, fields)) => {
|
||||||
return Some(fields[1]);
|
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,
|
UnOp::PtrMetadata,
|
||||||
Value::Cast {
|
Value::Cast {
|
||||||
@ -1421,7 +1421,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||||||
|
|
||||||
let mut inner = self.simplify_place_value(place, location)?;
|
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.
|
// Reborrowing copies length information from one pointer to the other.
|
||||||
while let Value::Address { place: borrowed, .. } = self.get(inner)
|
while let Value::Address { place: borrowed, .. } = self.get(inner)
|
||||||
&& let [PlaceElem::Deref] = borrowed.projection[..]
|
&& let [PlaceElem::Deref] = borrowed.projection[..]
|
||||||
@ -1430,7 +1430,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||||||
inner = borrowed;
|
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)
|
if let Value::Cast { kind, from, to, .. } = self.get(inner)
|
||||||
&& let CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _) = kind
|
&& let CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _) = kind
|
||||||
&& let Some(from) = from.builtin_deref(true)
|
&& let Some(from) = from.builtin_deref(true)
|
||||||
|
@ -119,7 +119,7 @@
|
|||||||
//!
|
//!
|
||||||
//! #### Unsizing Casts
|
//! #### Unsizing Casts
|
||||||
//! A subtle way of introducing use edges is by casting to a trait object.
|
//! 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
|
//! 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
|
//! pointers to these functions even if they never get called anywhere. This can
|
||||||
//! be seen as a special case of taking a function reference.
|
//! 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;
|
let span = self.body.source_info(location).span;
|
||||||
|
|
||||||
match *rvalue {
|
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
|
// have to instantiate all methods of the trait being cast to, so we
|
||||||
// can build the appropriate vtable.
|
// can build the appropriate vtable.
|
||||||
mir::Rvalue::Cast(
|
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
|
/// 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
|
/// Things can get more complicated though because there's also the case where
|
||||||
/// the unsized type occurs as a field:
|
/// 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`
|
/// 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
|
/// for the pair of `T` (which is a trait) and the concrete type that `T` was
|
||||||
/// originally coerced from:
|
/// originally coerced from:
|
||||||
///
|
///
|
||||||
|
@ -18,7 +18,7 @@ use std::path::Path;
|
|||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_ast::tokenstream::TokenStream;
|
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_ast_pretty::pprust;
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_errors::{Diag, FatalError, PResult};
|
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(
|
pub fn parse_cfg_attr(
|
||||||
cfg_attr: &Attribute,
|
cfg_attr: &Attribute,
|
||||||
psess: &ParseSess,
|
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_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]";
|
||||||
const CFG_ATTR_NOTE_REF: &str = "for more information, visit \
|
const CFG_ATTR_NOTE_REF: &str = "for more information, visit \
|
||||||
<https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>";
|
<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.
|
/// 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)>)> {
|
pub fn parse_cfg_attr(
|
||||||
let cfg_predicate = self.parse_meta_item(AllowLeadingUnsafe::No)?;
|
&mut self,
|
||||||
|
) -> PResult<'a, (ast::NestedMetaItem, Vec<(ast::AttrItem, Span)>)> {
|
||||||
|
let cfg_predicate = self.parse_meta_item_inner()?;
|
||||||
self.expect(&token::Comma)?;
|
self.expect(&token::Comma)?;
|
||||||
|
|
||||||
// Presumably, the majority of the time there will only be one attr.
|
// Presumably, the majority of the time there will only be one attr.
|
||||||
@ -452,7 +454,7 @@ impl<'a> Parser<'a> {
|
|||||||
/// ```ebnf
|
/// ```ebnf
|
||||||
/// MetaItemInner = UNSUFFIXED_LIT | MetaItem ;
|
/// 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() {
|
match self.parse_unsuffixed_meta_item_lit() {
|
||||||
Ok(lit) => return Ok(ast::NestedMetaItem::Lit(lit)),
|
Ok(lit) => return Ok(ast::NestedMetaItem::Lit(lit)),
|
||||||
Err(err) => err.cancel(), // we provide a better error below
|
Err(err) => err.cancel(), // we provide a better error below
|
||||||
|
@ -72,7 +72,7 @@ pub struct NativeLib {
|
|||||||
pub name: Symbol,
|
pub name: Symbol,
|
||||||
/// If packed_bundled_libs enabled, actual filename of library is stored.
|
/// If packed_bundled_libs enabled, actual filename of library is stored.
|
||||||
pub filename: Option<Symbol>,
|
pub filename: Option<Symbol>,
|
||||||
pub cfg: Option<ast::MetaItem>,
|
pub cfg: Option<ast::NestedMetaItem>,
|
||||||
pub foreign_module: Option<DefId>,
|
pub foreign_module: Option<DefId>,
|
||||||
pub verbatim: Option<bool>,
|
pub verbatim: Option<bool>,
|
||||||
pub dll_imports: Vec<DllImport>,
|
pub dll_imports: Vec<DllImport>,
|
||||||
|
@ -544,6 +544,7 @@ symbols! {
|
|||||||
cfg_accessible,
|
cfg_accessible,
|
||||||
cfg_attr,
|
cfg_attr,
|
||||||
cfg_attr_multi,
|
cfg_attr_multi,
|
||||||
|
cfg_boolean_literals,
|
||||||
cfg_doctest,
|
cfg_doctest,
|
||||||
cfg_eval,
|
cfg_eval,
|
||||||
cfg_fmt_debug,
|
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.
|
/// This is valid for both sized and unsized arguments.
|
||||||
pub fn make_indirect(&mut self) {
|
pub fn make_indirect(&mut self) {
|
||||||
match self.mode {
|
match self.mode {
|
||||||
|
@ -135,7 +135,7 @@ impl<'a> Layout<'a> {
|
|||||||
/// Note that the layout is NOT guaranteed to always be identical
|
/// Note that the layout is NOT guaranteed to always be identical
|
||||||
/// to that obtained from `layout_of(ty)`, as we need to produce
|
/// to that obtained from `layout_of(ty)`, as we need to produce
|
||||||
/// layouts for which Rust types do not exist, such as enum variants
|
/// 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)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)]
|
||||||
pub struct TyAndLayout<'a, Ty> {
|
pub struct TyAndLayout<'a, Ty> {
|
||||||
pub ty: Ty,
|
pub ty: Ty,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::iter;
|
use std::iter;
|
||||||
use std::path::PathBuf;
|
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_data_structures::fx::FxHashMap;
|
||||||
use rustc_errors::codes::*;
|
use rustc_errors::codes::*;
|
||||||
use rustc_errors::{ErrorGuaranteed, struct_span_code_err};
|
use rustc_errors::{ErrorGuaranteed, struct_span_code_err};
|
||||||
@ -282,7 +282,7 @@ pub struct OnUnimplementedFormatString {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct OnUnimplementedDirective {
|
pub struct OnUnimplementedDirective {
|
||||||
pub condition: Option<MetaItem>,
|
pub condition: Option<NestedMetaItem>,
|
||||||
pub subcommands: Vec<OnUnimplementedDirective>,
|
pub subcommands: Vec<OnUnimplementedDirective>,
|
||||||
pub message: Option<OnUnimplementedFormatString>,
|
pub message: Option<OnUnimplementedFormatString>,
|
||||||
pub label: Option<OnUnimplementedFormatString>,
|
pub label: Option<OnUnimplementedFormatString>,
|
||||||
@ -414,7 +414,7 @@ impl<'tcx> OnUnimplementedDirective {
|
|||||||
let cond = item_iter
|
let cond = item_iter
|
||||||
.next()
|
.next()
|
||||||
.ok_or_else(|| tcx.dcx().emit_err(EmptyOnClauseInOnUnimplemented { span }))?
|
.ok_or_else(|| tcx.dcx().emit_err(EmptyOnClauseInOnUnimplemented { span }))?
|
||||||
.meta_item()
|
.meta_item_or_bool()
|
||||||
.ok_or_else(|| tcx.dcx().emit_err(InvalidOnClauseInOnUnimplemented { span }))?;
|
.ok_or_else(|| tcx.dcx().emit_err(InvalidOnClauseInOnUnimplemented { span }))?;
|
||||||
attr::eval_condition(cond, &tcx.sess, Some(tcx.features()), &mut |cfg| {
|
attr::eval_condition(cond, &tcx.sess, Some(tcx.features()), &mut |cfg| {
|
||||||
if let Some(value) = cfg.value
|
if let Some(value) = cfg.value
|
||||||
@ -558,8 +558,8 @@ impl<'tcx> OnUnimplementedDirective {
|
|||||||
IgnoredDiagnosticOption::maybe_emit_warning(
|
IgnoredDiagnosticOption::maybe_emit_warning(
|
||||||
tcx,
|
tcx,
|
||||||
item_def_id,
|
item_def_id,
|
||||||
directive.condition.as_ref().map(|i| i.span),
|
directive.condition.as_ref().map(|i| i.span()),
|
||||||
aggr.condition.as_ref().map(|i| i.span),
|
aggr.condition.as_ref().map(|i| i.span()),
|
||||||
"condition",
|
"condition",
|
||||||
);
|
);
|
||||||
IgnoredDiagnosticOption::maybe_emit_warning(
|
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>(
|
fn adjust_for_rust_scalar<'tcx>(
|
||||||
cx: LayoutCx<'tcx>,
|
cx: LayoutCx<'tcx>,
|
||||||
attrs: &mut ArgAttributes,
|
attrs: &mut ArgAttributes,
|
||||||
@ -810,7 +810,7 @@ fn make_thin_self_ptr<'tcx>(
|
|||||||
layout: TyAndLayout<'tcx>,
|
layout: TyAndLayout<'tcx>,
|
||||||
) -> TyAndLayout<'tcx> {
|
) -> TyAndLayout<'tcx> {
|
||||||
let tcx = cx.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`
|
// unsized `self` is passed as a pointer to `self`
|
||||||
// FIXME (mikeyhew) change this to use &own if it is ever added to the language
|
// FIXME (mikeyhew) change this to use &own if it is ever added to the language
|
||||||
Ty::new_mut_ptr(tcx, layout.ty)
|
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`.
|
// 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
|
// To get the type `*mut RcBox<Self>`, we just keep unwrapping newtypes until we
|
||||||
// get a built-in pointer type
|
// get a built-in pointer type
|
||||||
let mut fat_pointer_layout = layout;
|
let mut wide_pointer_layout = layout;
|
||||||
while !fat_pointer_layout.ty.is_unsafe_ptr() && !fat_pointer_layout.ty.is_ref() {
|
while !wide_pointer_layout.ty.is_unsafe_ptr() && !wide_pointer_layout.ty.is_ref() {
|
||||||
fat_pointer_layout = fat_pointer_layout
|
wide_pointer_layout = wide_pointer_layout
|
||||||
.non_1zst_field(cx)
|
.non_1zst_field(cx)
|
||||||
.expect("not exactly one non-1-ZST field in a `DispatchFromDyn` type")
|
.expect("not exactly one non-1-ZST field in a `DispatchFromDyn` type")
|
||||||
.1
|
.1
|
||||||
}
|
}
|
||||||
|
|
||||||
fat_pointer_layout.ty
|
wide_pointer_layout.ty
|
||||||
};
|
};
|
||||||
|
|
||||||
// we now have a type like `*mut RcBox<dyn Trait>`
|
// 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);
|
let unit_ptr_ty = Ty::new_mut_ptr(tcx, tcx.types.unit);
|
||||||
|
|
||||||
TyAndLayout {
|
TyAndLayout {
|
||||||
ty: fat_pointer_ty,
|
ty: wide_pointer_ty,
|
||||||
|
|
||||||
// NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing the `Result`
|
// NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing the `Result`
|
||||||
// should always work because the type is always `*mut ()`.
|
// should always work because the type is always `*mut ()`.
|
||||||
|
@ -946,10 +946,10 @@ pub enum PointerCoercion {
|
|||||||
ArrayToPointer,
|
ArrayToPointer,
|
||||||
|
|
||||||
/// Unsize a pointer/reference value, e.g., `&[T; n]` to
|
/// Unsize a pointer/reference value, e.g., `&[T; n]` to
|
||||||
/// `&[T]`. Note that the source could be a thin or fat pointer.
|
/// `&[T]`. Note that the source could be a thin or wide pointer.
|
||||||
/// This will do things like convert thin pointers to fat
|
/// This will do things like convert thin pointers to wide
|
||||||
/// pointers, or convert structs containing thin pointers to
|
/// 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.
|
/// pointers.
|
||||||
Unsize,
|
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.
|
# the local version of the package is different than the one used by the CI.
|
||||||
ENV SCRIPT /tmp/checktools.sh ../x.py && \
|
ENV SCRIPT /tmp/checktools.sh ../x.py && \
|
||||||
npm install browser-ui-test@$(head -n 1 /tmp/browser-ui-test.version) --unsafe-perm=true && \
|
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::fmt::{self, Write};
|
||||||
use std::{mem, ops};
|
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_data_structures::fx::FxHashSet;
|
||||||
use rustc_feature::Features;
|
use rustc_feature::Features;
|
||||||
use rustc_session::parse::ParseSess;
|
use rustc_session::parse::ParseSess;
|
||||||
@ -48,6 +48,10 @@ impl Cfg {
|
|||||||
) -> Result<Option<Cfg>, InvalidCfgError> {
|
) -> Result<Option<Cfg>, InvalidCfgError> {
|
||||||
match nested_cfg {
|
match nested_cfg {
|
||||||
NestedMetaItem::MetaItem(ref cfg) => Cfg::parse_without(cfg, exclude),
|
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) => {
|
NestedMetaItem::Lit(ref lit) => {
|
||||||
Err(InvalidCfgError { msg: "unexpected literal", span: lit.span })
|
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
|
/// If the content is not properly formatted, it will return an error indicating what and where
|
||||||
/// the error is.
|
/// the error is.
|
||||||
pub(crate) fn parse(cfg: &MetaItem) -> Result<Cfg, InvalidCfgError> {
|
pub(crate) fn parse(cfg: &NestedMetaItem) -> Result<Cfg, InvalidCfgError> {
|
||||||
Self::parse_without(cfg, &FxHashSet::default()).map(|ret| ret.unwrap())
|
Self::parse_nested(cfg, &FxHashSet::default()).map(|ret| ret.unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks whether the given configuration can be matched in the current session.
|
/// 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::symbol::{Ident, kw};
|
||||||
use rustc_span::{DUMMY_SP, create_default_session_globals_then};
|
use rustc_span::{DUMMY_SP, create_default_session_globals_then};
|
||||||
use thin_vec::thin_vec;
|
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)))
|
Cfg::Cfg(Symbol::intern(name), Some(Symbol::intern(value)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dummy_meta_item_word(name: &str) -> MetaItem {
|
fn dummy_lit(symbol: Symbol, kind: LitKind) -> NestedMetaItem {
|
||||||
MetaItem {
|
NestedMetaItem::Lit(MetaItemLit { symbol, suffix: None, kind, span: DUMMY_SP })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dummy_meta_item_word(name: &str) -> NestedMetaItem {
|
||||||
|
NestedMetaItem::MetaItem(MetaItem {
|
||||||
unsafety: Safety::Default,
|
unsafety: Safety::Default,
|
||||||
path: Path::from_ident(Ident::from_str(name)),
|
path: Path::from_ident(Ident::from_str(name)),
|
||||||
kind: MetaItemKind::Word,
|
kind: MetaItemKind::Word,
|
||||||
span: DUMMY_SP,
|
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 };
|
let lit = MetaItemLit { symbol, suffix: None, kind, span: DUMMY_SP };
|
||||||
MetaItem {
|
NestedMetaItem::MetaItem(MetaItem {
|
||||||
unsafety: Safety::Default,
|
unsafety: Safety::Default,
|
||||||
path: Path::from_ident(Ident::from_str(name)),
|
path: Path::from_ident(Ident::from_str(name)),
|
||||||
kind: MetaItemKind::NameValue(lit),
|
kind: MetaItemKind::NameValue(lit),
|
||||||
span: DUMMY_SP,
|
span: DUMMY_SP,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! dummy_meta_item_list {
|
macro_rules! dummy_meta_item_list {
|
||||||
($name:ident, [$($list:ident),* $(,)?]) => {
|
($name:ident, [$($list:ident),* $(,)?]) => {
|
||||||
MetaItem {
|
NestedMetaItem::MetaItem(MetaItem {
|
||||||
unsafety: Safety::Default,
|
unsafety: Safety::Default,
|
||||||
path: Path::from_ident(Ident::from_str(stringify!($name))),
|
path: Path::from_ident(Ident::from_str(stringify!($name))),
|
||||||
kind: MetaItemKind::List(thin_vec![
|
kind: MetaItemKind::List(thin_vec![
|
||||||
$(
|
$(
|
||||||
NestedMetaItem::MetaItem(
|
dummy_meta_item_word(stringify!($list)),
|
||||||
dummy_meta_item_word(stringify!($list)),
|
|
||||||
),
|
|
||||||
)*
|
)*
|
||||||
]),
|
]),
|
||||||
span: DUMMY_SP,
|
span: DUMMY_SP,
|
||||||
}
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
($name:ident, [$($list:expr),* $(,)?]) => {
|
($name:ident, [$($list:expr),* $(,)?]) => {
|
||||||
MetaItem {
|
NestedMetaItem::MetaItem(MetaItem {
|
||||||
unsafety: Safety::Default,
|
unsafety: Safety::Default,
|
||||||
path: Path::from_ident(Ident::from_str(stringify!($name))),
|
path: Path::from_ident(Ident::from_str(stringify!($name))),
|
||||||
kind: MetaItemKind::List(thin_vec![
|
kind: MetaItemKind::List(thin_vec![
|
||||||
$(
|
$($list,)*
|
||||||
NestedMetaItem::MetaItem($list),
|
|
||||||
)*
|
|
||||||
]),
|
]),
|
||||||
span: DUMMY_SP,
|
span: DUMMY_SP,
|
||||||
}
|
})
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,6 +252,14 @@ fn test_cfg_or() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_parse_ok() {
|
fn test_parse_ok() {
|
||||||
create_default_session_globals_then(|| {
|
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");
|
let mi = dummy_meta_item_word("all");
|
||||||
assert_eq!(Cfg::parse(&mi), Ok(word_cfg("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, []),]);
|
let mi = dummy_meta_item_list!(not, [dummy_meta_item_list!(foo, []),]);
|
||||||
assert!(Cfg::parse(&mi).is_err());
|
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 std::{fmt, iter};
|
||||||
|
|
||||||
use arrayvec::ArrayVec;
|
use arrayvec::ArrayVec;
|
||||||
|
use rustc_ast::NestedMetaItem;
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_attr::{ConstStability, Deprecation, Stability, StableSince};
|
use rustc_attr::{ConstStability, Deprecation, Stability, StableSince};
|
||||||
use rustc_const_eval::const_eval::is_unstable_const_fn;
|
use rustc_const_eval::const_eval::is_unstable_const_fn;
|
||||||
@ -986,7 +987,7 @@ pub(crate) trait AttributesExt {
|
|||||||
.peekable();
|
.peekable();
|
||||||
if doc_cfg.peek().is_some() && doc_cfg_active {
|
if doc_cfg.peek().is_some() && doc_cfg_active {
|
||||||
doc_cfg
|
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)
|
.fold(Cfg::True, |cfg, new_cfg| cfg & new_cfg)
|
||||||
} else if doc_auto_cfg_active {
|
} else if doc_auto_cfg_active {
|
||||||
// If there is no `doc(cfg())`, then we retrieve the `cfg()` attributes (because
|
// 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();
|
let mut meta = attr.meta_item().unwrap().clone();
|
||||||
meta.path = ast::Path::from_ident(Ident::with_dummy_span(sym::target_feature));
|
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;
|
cfg &= feat_cfg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||||||
.unwrap_or(&[])
|
.unwrap_or(&[])
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|attr| {
|
.filter_map(|attr| {
|
||||||
Cfg::parse(attr.meta_item()?)
|
Cfg::parse(attr)
|
||||||
.map_err(|e| self.cx.sess().dcx().span_err(e.span, e.msg))
|
.map_err(|e| self.cx.sess().dcx().span_err(e.span, e.msg))
|
||||||
.ok()
|
.ok()
|
||||||
})
|
})
|
||||||
|
@ -19,7 +19,6 @@ function showHelp() {
|
|||||||
console.log(" --debug : show extra information about script run");
|
console.log(" --debug : show extra information about script run");
|
||||||
console.log(" --show-text : render font in pages");
|
console.log(" --show-text : render font in pages");
|
||||||
console.log(" --no-headless : disable headless mode");
|
console.log(" --no-headless : disable headless mode");
|
||||||
console.log(" --no-sandbox : disable sandbox mode");
|
|
||||||
console.log(" --help : show this message then quit");
|
console.log(" --help : show this message then quit");
|
||||||
console.log(" --tests-folder [PATH] : location of the .GOML tests folder");
|
console.log(" --tests-folder [PATH] : location of the .GOML tests folder");
|
||||||
console.log(" --jobs [NUMBER] : number of threads to run tests on");
|
console.log(" --jobs [NUMBER] : number of threads to run tests on");
|
||||||
@ -40,7 +39,6 @@ function parseOptions(args) {
|
|||||||
"no_headless": false,
|
"no_headless": false,
|
||||||
"jobs": -1,
|
"jobs": -1,
|
||||||
"executable_path": null,
|
"executable_path": null,
|
||||||
"no_sandbox": false,
|
|
||||||
};
|
};
|
||||||
const correspondences = {
|
const correspondences = {
|
||||||
"--doc-folder": "doc_folder",
|
"--doc-folder": "doc_folder",
|
||||||
@ -49,7 +47,6 @@ function parseOptions(args) {
|
|||||||
"--show-text": "show_text",
|
"--show-text": "show_text",
|
||||||
"--no-headless": "no_headless",
|
"--no-headless": "no_headless",
|
||||||
"--executable-path": "executable_path",
|
"--executable-path": "executable_path",
|
||||||
"--no-sandbox": "no_sandbox",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for (let i = 0; i < args.length; ++i) {
|
for (let i = 0; i < args.length; ++i) {
|
||||||
@ -80,9 +77,6 @@ function parseOptions(args) {
|
|||||||
} else if (arg === "--help") {
|
} else if (arg === "--help") {
|
||||||
showHelp();
|
showHelp();
|
||||||
process.exit(0);
|
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]) {
|
} else if (correspondences[arg]) {
|
||||||
opts[correspondences[arg]] = true;
|
opts[correspondences[arg]] = true;
|
||||||
} else {
|
} else {
|
||||||
@ -203,6 +197,7 @@ async function main(argv) {
|
|||||||
const args = [
|
const args = [
|
||||||
"--variable", "DOC_PATH", opts["doc_folder"].split("\\").join("/"),
|
"--variable", "DOC_PATH", opts["doc_folder"].split("\\").join("/"),
|
||||||
"--enable-fail-on-js-error", "--allow-file-access-from-files",
|
"--enable-fail-on-js-error", "--allow-file-access-from-files",
|
||||||
|
"--no-sandbox",
|
||||||
];
|
];
|
||||||
if (opts["debug"]) {
|
if (opts["debug"]) {
|
||||||
debug = true;
|
debug = true;
|
||||||
@ -211,9 +206,6 @@ async function main(argv) {
|
|||||||
if (opts["show_text"]) {
|
if (opts["show_text"]) {
|
||||||
args.push("--show-text");
|
args.push("--show-text");
|
||||||
}
|
}
|
||||||
if (opts["no_sandbox"]) {
|
|
||||||
args.push("--no-sandbox");
|
|
||||||
}
|
|
||||||
if (opts["no_headless"]) {
|
if (opts["no_headless"]) {
|
||||||
args.push("--no-headless");
|
args.push("--no-headless");
|
||||||
headless = false;
|
headless = false;
|
||||||
@ -262,19 +254,6 @@ async function main(argv) {
|
|||||||
console.log(`Running ${files.length} rustdoc-gui ...`);
|
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 originalFilesLen = files.length;
|
||||||
const results = createEmptyResults();
|
const results = createEmptyResults();
|
||||||
const status_bar = char_printer(files.length);
|
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.failed, new_results.failed);
|
||||||
Array.prototype.push.apply(results.errored, new_results.errored);
|
Array.prototype.push.apply(results.errored, new_results.errored);
|
||||||
|
|
||||||
// We don't need this listener anymore.
|
|
||||||
process.removeListener("exit", exitHandling);
|
|
||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
results.successful.sort(by_filename);
|
results.successful.sort(by_filename);
|
||||||
results.successful.forEach(r => {
|
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`.
|
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/
|
[browser-ui-test]: https://github.com/GuillaumeGomez/browser-UI-test/
|
||||||
[puppeteer]: https://pptr.dev/
|
[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
|
= 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
|
--> $DIR/fat-ptr-cast.rs:19:5
|
||||||
|
|
|
|
||||||
LL | q as *const [i32];
|
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
|
--> $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) };
|
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
|
--> $DIR/E0607.rs:3:5
|
||||||
|
|
|
|
||||||
LL | v as *const [u8];
|
LL | v as *const [u8];
|
||||||
|
@ -81,7 +81,7 @@ help: dereference the expression
|
|||||||
LL | let y: u32 = *x as u32;
|
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
|
--> $DIR/error-festival.rs:41:5
|
||||||
|
|
|
|
||||||
LL | v as *const [u8];
|
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 ()) {
|
fn cast_thin_to_fat(x: *const ()) {
|
||||||
x as *const [u8];
|
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() {}
|
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
|
--> $DIR/issue-31511.rs:2:5
|
||||||
|
|
|
|
||||||
LL | x as *const [u8];
|
LL | x as *const [u8];
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
fn main() {
|
fn main() {
|
||||||
cfg!(); //~ ERROR macro requires a cfg-pattern
|
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 = 123); //~ ERROR literal in `cfg` predicate value must be a string
|
||||||
cfg!(foo, bar); //~ ERROR expected 1 cfg-pattern
|
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)
|
= 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
|
--> $DIR/cfg.rs:3:10
|
||||||
|
|
|
|
||||||
LL | cfg!(123);
|
LL | cfg!(123);
|
||||||
| ^^^ expected identifier
|
| ^^^
|
||||||
|
|
||||||
error[E0565]: literal in `cfg` predicate value must be a string
|
error[E0565]: literal in `cfg` predicate value must be a string
|
||||||
--> $DIR/cfg.rs:4:16
|
--> $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`
|
| 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
|
--> $DIR/cast-rfc0401.rs:52:13
|
||||||
|
|
|
|
||||||
LL | let _ = v as *const [u8];
|
LL | let _ = v as *const [u8];
|
||||||
|
@ -925,6 +925,7 @@ users_on_vacation = [
|
|||||||
"jhpratt",
|
"jhpratt",
|
||||||
"jyn514",
|
"jyn514",
|
||||||
"oli-obk",
|
"oli-obk",
|
||||||
|
"jieyouxu",
|
||||||
]
|
]
|
||||||
|
|
||||||
[assign.adhoc_groups]
|
[assign.adhoc_groups]
|
||||||
|
Loading…
Reference in New Issue
Block a user