mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 11:07:42 +00:00
Auto merge of #82153 - jonas-schievink:rollup-ls5r943, r=jonas-schievink
Rollup of 19 pull requests Successful merges: - #81503 (Suggest to create a new `const` item if the `fn` in the array is a `const fn`) - #81897 (Add match pattern diagnostics regression test) - #81975 (Seal the CommandExt, OsStrExt and OsStringExt traits) - #82009 (const_generics: Dont evaluate array length const when handling errors) - #82060 (Fix typos in BTreeSet::{first, last} docs) - #82061 (CTFE validation: catch ReadPointerAsBytes and better error) - #82063 (Fixed minor typo in catch_unwind docs) - #82067 (const_generics: Fix incorrect ty::ParamEnv::empty() usage) - #82077 (Edit `rustc_arena::DropArena` docs) - #82096 (Fix a typo) - #82106 (Remove unnecessary `Option` in `default_doc`) - #82107 (expand: Some cleanup) - #82118 (Add missing env!-decl variant) - #82119 (Fix typo in link to CreateSymbolicLinkW documentation.) - #82120 (Stabilize Arguments::as_str) - #82129 (Remove redundant bool_to_option feature gate) - #82133 (Update link for extern prelude.) - #82141 (32-bit ARM: Emit `lr` instead of `r14` when specified as an `asm!` output register.) - #82147 (⬆️ rust-analyzer) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
42a4673fbd
@ -568,10 +568,13 @@ impl Drop for DropType {
|
||||
}
|
||||
|
||||
/// An arena which can be used to allocate any type.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Allocating in this arena is unsafe since the type system
|
||||
/// doesn't know which types it contains. In order to
|
||||
/// allocate safely, you must store a PhantomData<T>
|
||||
/// alongside this arena for each type T you allocate.
|
||||
/// allocate safely, you must store a `PhantomData<T>`
|
||||
/// alongside this arena for each type `T` you allocate.
|
||||
#[derive(Default)]
|
||||
pub struct DropArena {
|
||||
/// A list of destructors to run when the arena drops.
|
||||
@ -589,7 +592,7 @@ impl DropArena {
|
||||
ptr::write(mem, object);
|
||||
let result = &mut *mem;
|
||||
// Record the destructor after doing the allocation as that may panic
|
||||
// and would cause `object`'s destructor to run twice if it was recorded before
|
||||
// and would cause `object`'s destructor to run twice if it was recorded before.
|
||||
self.destructors
|
||||
.borrow_mut()
|
||||
.push(DropType { drop_fn: drop_for_type::<T>, obj: result as *mut T as *mut u8 });
|
||||
@ -607,16 +610,16 @@ impl DropArena {
|
||||
let start_ptr = self.arena.alloc_raw(Layout::array::<T>(len).unwrap()) as *mut T;
|
||||
|
||||
let mut destructors = self.destructors.borrow_mut();
|
||||
// Reserve space for the destructors so we can't panic while adding them
|
||||
// Reserve space for the destructors so we can't panic while adding them.
|
||||
destructors.reserve(len);
|
||||
|
||||
// Move the content to the arena by copying it and then forgetting
|
||||
// the content of the SmallVec
|
||||
// the content of the SmallVec.
|
||||
vec.as_ptr().copy_to_nonoverlapping(start_ptr, len);
|
||||
mem::forget(vec.drain(..));
|
||||
|
||||
// Record the destructors after doing the allocation as that may panic
|
||||
// and would cause `object`'s destructor to run twice if it was recorded before
|
||||
// and would cause `object`'s destructor to run twice if it was recorded before.
|
||||
for i in 0..len {
|
||||
destructors
|
||||
.push(DropType { drop_fn: drop_for_type::<T>, obj: start_ptr.add(i) as *mut u8 });
|
||||
|
@ -487,6 +487,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
|
||||
} else if reg == InlineAsmReg::AArch64(AArch64InlineAsmReg::x30) {
|
||||
// LLVM doesn't recognize x30
|
||||
"{lr}".to_string()
|
||||
} else if reg == InlineAsmReg::Arm(ArmInlineAsmReg::r14) {
|
||||
// LLVM doesn't recognize r14
|
||||
"{lr}".to_string()
|
||||
} else {
|
||||
format!("{{{}}}", reg.name())
|
||||
}
|
||||
|
@ -1067,8 +1067,6 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
||||
fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
|
||||
self.cfg.configure_expr(expr);
|
||||
visit_clobber(expr.deref_mut(), |mut expr| {
|
||||
self.cfg.configure_expr_kind(&mut expr.kind);
|
||||
|
||||
if let Some(attr) = self.take_first_attr(&mut expr) {
|
||||
// Collect the invoc regardless of whether or not attributes are permitted here
|
||||
// expansion will eat the attribute so it won't error later.
|
||||
@ -1166,8 +1164,6 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
||||
fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
|
||||
let expr = configure!(self, expr);
|
||||
expr.filter_map(|mut expr| {
|
||||
self.cfg.configure_expr_kind(&mut expr.kind);
|
||||
|
||||
if let Some(attr) = self.take_first_attr(&mut expr) {
|
||||
self.cfg.maybe_emit_expr_attr_err(&attr.0);
|
||||
|
||||
@ -1192,7 +1188,6 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
||||
}
|
||||
|
||||
fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
|
||||
self.cfg.configure_pat(pat);
|
||||
match pat.kind {
|
||||
PatKind::MacCall(_) => {}
|
||||
_ => return noop_visit_pat(pat, self),
|
||||
@ -1406,15 +1401,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) {
|
||||
self.cfg.configure_foreign_mod(foreign_mod);
|
||||
noop_visit_foreign_mod(foreign_mod, self);
|
||||
}
|
||||
|
||||
fn flat_map_foreign_item(
|
||||
&mut self,
|
||||
mut foreign_item: P<ast::ForeignItem>,
|
||||
foreign_item: P<ast::ForeignItem>,
|
||||
) -> SmallVec<[P<ast::ForeignItem>; 1]> {
|
||||
let mut foreign_item = configure!(self, foreign_item);
|
||||
|
||||
if let Some(attr) = self.take_first_attr(&mut foreign_item) {
|
||||
return self
|
||||
.collect_attr(
|
||||
@ -1439,11 +1431,6 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_item_kind(&mut self, item: &mut ast::ItemKind) {
|
||||
self.cfg.configure_item_kind(item);
|
||||
noop_visit_item_kind(item, self);
|
||||
}
|
||||
|
||||
fn flat_map_generic_param(
|
||||
&mut self,
|
||||
param: ast::GenericParam,
|
||||
@ -1602,11 +1589,6 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
|
||||
*id = self.cx.resolver.next_node_id()
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_fn_decl(&mut self, mut fn_decl: &mut P<ast::FnDecl>) {
|
||||
self.cfg.configure_fn_decl(&mut fn_decl);
|
||||
noop_visit_fn_decl(fn_decl, self);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ExpansionConfig<'feat> {
|
||||
@ -1614,9 +1596,8 @@ pub struct ExpansionConfig<'feat> {
|
||||
pub features: Option<&'feat Features>,
|
||||
pub recursion_limit: Limit,
|
||||
pub trace_mac: bool,
|
||||
pub should_test: bool, // If false, strip `#[test]` nodes
|
||||
pub keep_macs: bool,
|
||||
pub span_debug: bool, // If true, use verbose debugging for `proc_macro::Span`
|
||||
pub should_test: bool, // If false, strip `#[test]` nodes
|
||||
pub span_debug: bool, // If true, use verbose debugging for `proc_macro::Span`
|
||||
pub proc_macro_backtrace: bool, // If true, show backtraces for proc-macro panics
|
||||
}
|
||||
|
||||
@ -1628,7 +1609,6 @@ impl<'feat> ExpansionConfig<'feat> {
|
||||
recursion_limit: Limit::new(1024),
|
||||
trace_mac: false,
|
||||
should_test: false,
|
||||
keep_macs: false,
|
||||
span_debug: false,
|
||||
proc_macro_backtrace: false,
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
#![feature(bool_to_option)]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(or_patterns)]
|
||||
|
@ -371,12 +371,4 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mod(&mut self, module: &mut ast::Mod) {
|
||||
noop_visit_mod(module, self);
|
||||
// remove macro definitions
|
||||
module.items.retain(
|
||||
|item| !matches!(item.kind, ast::ItemKind::MacCall(_) if !self.cx.ecfg.keep_macs),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -639,6 +639,10 @@ struct QueryTypeRelatingDelegate<'a, 'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||
self.param_env
|
||||
}
|
||||
|
||||
fn create_next_universe(&mut self) -> ty::UniverseIndex {
|
||||
self.infcx.create_next_universe()
|
||||
}
|
||||
|
@ -221,6 +221,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
|
||||
/// As `3 + 4` contains `N` in its substs, this must not succeed.
|
||||
///
|
||||
/// See `src/test/ui/const-generics/occurs-check/` for more examples where this is relevant.
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn unify_const_variable(
|
||||
&self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
|
@ -72,6 +72,8 @@ where
|
||||
}
|
||||
|
||||
pub trait TypeRelatingDelegate<'tcx> {
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx>;
|
||||
|
||||
/// Push a constraint `sup: sub` -- this constraint must be
|
||||
/// satisfied for the two types to be related. `sub` and `sup` may
|
||||
/// be regions from the type or new variables created through the
|
||||
@ -473,9 +475,8 @@ where
|
||||
self.infcx.tcx
|
||||
}
|
||||
|
||||
// FIXME(oli-obk): not sure how to get the correct ParamEnv
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||
ty::ParamEnv::empty()
|
||||
self.delegate.param_env()
|
||||
}
|
||||
|
||||
fn tag(&self) -> &'static str {
|
||||
@ -819,9 +820,8 @@ where
|
||||
self.infcx.tcx
|
||||
}
|
||||
|
||||
// FIXME(oli-obk): not sure how to get the correct ParamEnv
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||
ty::ParamEnv::empty()
|
||||
self.delegate.param_env()
|
||||
}
|
||||
|
||||
fn tag(&self) -> &'static str {
|
||||
|
@ -31,6 +31,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
/// constant `bar::<T>()` requires a substitution for `T`, if the substitution for `T` is still
|
||||
/// too generic for the constant to be evaluated then `Err(ErrorHandled::TooGeneric)` is
|
||||
/// returned.
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
pub fn const_eval_resolve(
|
||||
self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
|
@ -228,7 +228,10 @@ pub enum ObligationCauseCode<'tcx> {
|
||||
/// Inline asm operand type must be `Sized`.
|
||||
InlineAsmSized,
|
||||
/// `[T, ..n]` implies that `T` must be `Copy`.
|
||||
RepeatVec,
|
||||
/// If the function in the array repeat expression is a `const fn`,
|
||||
/// display a help message suggesting to move the function call to a
|
||||
/// new `const` item while saying that `T` doesn't implement `Copy`.
|
||||
RepeatVec(bool),
|
||||
|
||||
/// Types of fields (other than the last, except for packed structs) in a struct must be sized.
|
||||
FieldSized {
|
||||
|
@ -228,12 +228,17 @@ impl<'tcx> ty::TyS<'tcx> {
|
||||
ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.def_path_str(def.did)).into(),
|
||||
ty::Foreign(def_id) => format!("extern type `{}`", tcx.def_path_str(def_id)).into(),
|
||||
ty::Array(t, n) => {
|
||||
let n = tcx.lift(n).unwrap();
|
||||
match n.try_eval_usize(tcx, ty::ParamEnv::empty()) {
|
||||
_ if t.is_simple_ty() => format!("array `{}`", self).into(),
|
||||
Some(n) => format!("array of {} element{}", n, pluralize!(n)).into(),
|
||||
None => "array".into(),
|
||||
if t.is_simple_ty() {
|
||||
return format!("array `{}`", self).into();
|
||||
}
|
||||
|
||||
let n = tcx.lift(n).unwrap();
|
||||
if let ty::ConstKind::Value(v) = n.val {
|
||||
if let Some(n) = v.try_to_machine_usize(tcx) {
|
||||
return format!("array of {} element{}", n, pluralize!(n)).into();
|
||||
}
|
||||
}
|
||||
"array".into()
|
||||
}
|
||||
ty::Slice(ty) if ty.is_simple_ty() => format!("slice `{}`", self).into(),
|
||||
ty::Slice(_) => "slice".into(),
|
||||
|
@ -347,6 +347,7 @@ impl<'tcx> Instance<'tcx> {
|
||||
}
|
||||
|
||||
// This should be kept up to date with `resolve`.
|
||||
#[instrument(level = "debug", skip(tcx))]
|
||||
pub fn resolve_opt_const_arg(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
|
@ -43,6 +43,9 @@ use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligations}
|
||||
use crate::dataflow::impls::MaybeInitializedPlaces;
|
||||
use crate::dataflow::move_paths::MoveData;
|
||||
use crate::dataflow::ResultsCursor;
|
||||
use crate::transform::{
|
||||
check_consts::ConstCx, promote_consts::is_const_fn_in_array_repeat_expression,
|
||||
};
|
||||
|
||||
use crate::borrow_check::{
|
||||
borrow_set::BorrowSet,
|
||||
@ -1098,6 +1101,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
) -> Fallible<()> {
|
||||
relate_tys::relate_types(
|
||||
self.infcx,
|
||||
self.param_env,
|
||||
a,
|
||||
v,
|
||||
b,
|
||||
@ -1988,18 +1992,24 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
Operand::Copy(..) | Operand::Constant(..) => {
|
||||
// These are always okay: direct use of a const, or a value that can evidently be copied.
|
||||
}
|
||||
Operand::Move(_) => {
|
||||
Operand::Move(place) => {
|
||||
// Make sure that repeated elements implement `Copy`.
|
||||
let span = body.source_info(location).span;
|
||||
let ty = operand.ty(body, tcx);
|
||||
if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty, span) {
|
||||
let ccx = ConstCx::new_with_param_env(tcx, body, self.param_env);
|
||||
let is_const_fn =
|
||||
is_const_fn_in_array_repeat_expression(&ccx, &place, &body);
|
||||
|
||||
debug!("check_rvalue: is_const_fn={:?}", is_const_fn);
|
||||
|
||||
let def_id = body.source.def_id().expect_local();
|
||||
self.infcx.report_selection_error(
|
||||
&traits::Obligation::new(
|
||||
ObligationCause::new(
|
||||
span,
|
||||
self.tcx().hir().local_def_id_to_hir_id(def_id),
|
||||
traits::ObligationCauseCode::RepeatVec,
|
||||
traits::ObligationCauseCode::RepeatVec(is_const_fn),
|
||||
),
|
||||
self.param_env,
|
||||
ty::Binder::bind(ty::TraitRef::new(
|
||||
|
@ -18,6 +18,7 @@ use crate::borrow_check::type_check::{BorrowCheckContext, Locations};
|
||||
/// variables, but not the type `b`.
|
||||
pub(super) fn relate_types<'tcx>(
|
||||
infcx: &InferCtxt<'_, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
a: Ty<'tcx>,
|
||||
v: ty::Variance,
|
||||
b: Ty<'tcx>,
|
||||
@ -28,7 +29,7 @@ pub(super) fn relate_types<'tcx>(
|
||||
debug!("relate_types(a={:?}, v={:?}, b={:?}, locations={:?})", a, v, b, locations);
|
||||
TypeRelating::new(
|
||||
infcx,
|
||||
NllTypeRelatingDelegate::new(infcx, borrowck_context, locations, category),
|
||||
NllTypeRelatingDelegate::new(infcx, borrowck_context, param_env, locations, category),
|
||||
v,
|
||||
)
|
||||
.relate(a, b)?;
|
||||
@ -39,6 +40,8 @@ struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
|
||||
infcx: &'me InferCtxt<'me, 'tcx>,
|
||||
borrowck_context: Option<&'me mut BorrowCheckContext<'bccx, 'tcx>>,
|
||||
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
|
||||
/// Where (and why) is this relation taking place?
|
||||
locations: Locations,
|
||||
|
||||
@ -50,14 +53,19 @@ impl NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
|
||||
fn new(
|
||||
infcx: &'me InferCtxt<'me, 'tcx>,
|
||||
borrowck_context: Option<&'me mut BorrowCheckContext<'bccx, 'tcx>>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
locations: Locations,
|
||||
category: ConstraintCategory,
|
||||
) -> Self {
|
||||
Self { infcx, borrowck_context, locations, category }
|
||||
Self { infcx, borrowck_context, param_env, locations, category }
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> {
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||
self.param_env
|
||||
}
|
||||
|
||||
fn create_next_universe(&mut self) -> ty::UniverseIndex {
|
||||
self.infcx.create_next_universe()
|
||||
}
|
||||
|
@ -208,7 +208,7 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
|
||||
) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> {
|
||||
// see comment in const_eval_raw_provider for what we're doing here
|
||||
// see comment in eval_to_allocation_raw_provider for what we're doing here
|
||||
if key.param_env.reveal() == Reveal::All {
|
||||
let mut key = key;
|
||||
key.param_env = key.param_env.with_user_facing();
|
||||
|
@ -21,7 +21,7 @@ use std::hash::Hash;
|
||||
|
||||
use super::{
|
||||
CheckInAllocMsg, GlobalAlloc, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy,
|
||||
ValueVisitor,
|
||||
ScalarMaybeUninit, ValueVisitor,
|
||||
};
|
||||
|
||||
macro_rules! throw_validation_failure {
|
||||
@ -378,7 +378,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||
value: OpTy<'tcx, M::PointerTag>,
|
||||
kind: &str,
|
||||
) -> InterpResult<'tcx> {
|
||||
let value = self.ecx.read_immediate(value)?;
|
||||
let value = try_validation!(
|
||||
self.ecx.read_immediate(value),
|
||||
self.path,
|
||||
err_unsup!(ReadPointerAsBytes) => { "part of a pointer" } expected { "a proper pointer or integer value" },
|
||||
);
|
||||
// Handle wide pointers.
|
||||
// Check metadata early, for better diagnostics
|
||||
let place = try_validation!(
|
||||
@ -485,6 +489,17 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_scalar(
|
||||
&self,
|
||||
op: OpTy<'tcx, M::PointerTag>,
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<M::PointerTag>> {
|
||||
Ok(try_validation!(
|
||||
self.ecx.read_scalar(op),
|
||||
self.path,
|
||||
err_unsup!(ReadPointerAsBytes) => { "(potentially part of) a pointer" } expected { "plain (non-pointer) bytes" },
|
||||
))
|
||||
}
|
||||
|
||||
/// Check if this is a value of primitive type, and if yes check the validity of the value
|
||||
/// at that type. Return `true` if the type is indeed primitive.
|
||||
fn try_visit_primitive(
|
||||
@ -495,7 +510,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||
let ty = value.layout.ty;
|
||||
match ty.kind() {
|
||||
ty::Bool => {
|
||||
let value = self.ecx.read_scalar(value)?;
|
||||
let value = self.read_scalar(value)?;
|
||||
try_validation!(
|
||||
value.to_bool(),
|
||||
self.path,
|
||||
@ -505,7 +520,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||
Ok(true)
|
||||
}
|
||||
ty::Char => {
|
||||
let value = self.ecx.read_scalar(value)?;
|
||||
let value = self.read_scalar(value)?;
|
||||
try_validation!(
|
||||
value.to_char(),
|
||||
self.path,
|
||||
@ -515,11 +530,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||
Ok(true)
|
||||
}
|
||||
ty::Float(_) | ty::Int(_) | ty::Uint(_) => {
|
||||
let value = try_validation!(
|
||||
self.ecx.read_scalar(value),
|
||||
self.path,
|
||||
err_unsup!(ReadPointerAsBytes) => { "read of part of a pointer" },
|
||||
);
|
||||
let value = self.read_scalar(value)?;
|
||||
// NOTE: Keep this in sync with the array optimization for int/float
|
||||
// types below!
|
||||
if self.ctfe_mode.is_some() {
|
||||
@ -541,9 +552,10 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||
// actually enforce the strict rules for raw pointers (mostly because
|
||||
// that lets us re-use `ref_to_mplace`).
|
||||
let place = try_validation!(
|
||||
self.ecx.ref_to_mplace(self.ecx.read_immediate(value)?),
|
||||
self.ecx.read_immediate(value).and_then(|i| self.ecx.ref_to_mplace(i)),
|
||||
self.path,
|
||||
err_ub!(InvalidUninitBytes(None)) => { "uninitialized raw pointer" },
|
||||
err_unsup!(ReadPointerAsBytes) => { "part of a pointer" } expected { "a proper pointer or integer value" },
|
||||
);
|
||||
if place.layout.is_unsized() {
|
||||
self.check_wide_ptr_meta(place.meta, place.layout)?;
|
||||
@ -569,9 +581,13 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||
Ok(true)
|
||||
}
|
||||
ty::FnPtr(_sig) => {
|
||||
let value = self.ecx.read_scalar(value)?;
|
||||
let value = try_validation!(
|
||||
self.ecx.read_immediate(value),
|
||||
self.path,
|
||||
err_unsup!(ReadPointerAsBytes) => { "part of a pointer" } expected { "a proper pointer or integer value" },
|
||||
);
|
||||
let _fn = try_validation!(
|
||||
value.check_init().and_then(|ptr| self.ecx.memory.get_fn(ptr)),
|
||||
value.to_scalar().and_then(|ptr| self.ecx.memory.get_fn(ptr)),
|
||||
self.path,
|
||||
err_ub!(DanglingIntPointer(..)) |
|
||||
err_ub!(InvalidFunctionPointer(..)) |
|
||||
@ -615,7 +631,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
||||
op: OpTy<'tcx, M::PointerTag>,
|
||||
scalar_layout: &Scalar,
|
||||
) -> InterpResult<'tcx> {
|
||||
let value = self.ecx.read_scalar(op)?;
|
||||
let value = self.read_scalar(op)?;
|
||||
let valid_range = &scalar_layout.valid_range;
|
||||
let (lo, hi) = valid_range.clone().into_inner();
|
||||
// Determine the allowed range
|
||||
|
@ -1231,3 +1231,38 @@ pub fn promote_candidates<'tcx>(
|
||||
|
||||
promotions
|
||||
}
|
||||
|
||||
/// This function returns `true` if the function being called in the array
|
||||
/// repeat expression is a `const` function.
|
||||
crate fn is_const_fn_in_array_repeat_expression<'tcx>(
|
||||
ccx: &ConstCx<'_, 'tcx>,
|
||||
place: &Place<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
) -> bool {
|
||||
match place.as_local() {
|
||||
// rule out cases such as: `let my_var = some_fn(); [my_var; N]`
|
||||
Some(local) if body.local_decls[local].is_user_variable() => return false,
|
||||
None => return false,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
for block in body.basic_blocks() {
|
||||
if let Some(Terminator { kind: TerminatorKind::Call { func, destination, .. }, .. }) =
|
||||
&block.terminator
|
||||
{
|
||||
if let Operand::Constant(box Constant { literal: ty::Const { ty, .. }, .. }) = func {
|
||||
if let ty::FnDef(def_id, _) = *ty.kind() {
|
||||
if let Some((destination_place, _)) = destination {
|
||||
if destination_place == place {
|
||||
if is_const_fn(ccx.tcx, def_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
@ -510,11 +510,10 @@ impl Span {
|
||||
/// items can be used (that is, a macro marked with
|
||||
/// `#[allow_internal_unstable]`).
|
||||
pub fn allows_unstable(&self, feature: Symbol) -> bool {
|
||||
self.ctxt().outer_expn_data().allow_internal_unstable.map_or(false, |features| {
|
||||
features
|
||||
.iter()
|
||||
.any(|&f| f == feature || f == sym::allow_internal_unstable_backcompat_hack)
|
||||
})
|
||||
self.ctxt()
|
||||
.outer_expn_data()
|
||||
.allow_internal_unstable
|
||||
.map_or(false, |features| features.iter().any(|&f| f == feature))
|
||||
}
|
||||
|
||||
/// Checks if this span arises from a compiler desugaring of kind `kind`.
|
||||
|
@ -252,7 +252,6 @@ symbols! {
|
||||
allow_fail,
|
||||
allow_internal_unsafe,
|
||||
allow_internal_unstable,
|
||||
allow_internal_unstable_backcompat_hack,
|
||||
allowed,
|
||||
always,
|
||||
and,
|
||||
|
@ -1881,10 +1881,26 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
ObligationCauseCode::Coercion { source: _, target } => {
|
||||
err.note(&format!("required by cast to type `{}`", self.ty_to_string(target)));
|
||||
}
|
||||
ObligationCauseCode::RepeatVec => {
|
||||
ObligationCauseCode::RepeatVec(is_const_fn) => {
|
||||
err.note(
|
||||
"the `Copy` trait is required because the repeated element will be copied",
|
||||
);
|
||||
|
||||
if is_const_fn {
|
||||
err.help(
|
||||
"consider creating a new `const` item and initializing with the result \
|
||||
of the function call to be used in the repeat position, like \
|
||||
`const VAL: Type = const_fn();` and `let x = [VAL; 42];`",
|
||||
);
|
||||
}
|
||||
|
||||
if self.tcx.sess.is_nightly_build() && is_const_fn {
|
||||
err.help(
|
||||
"create an inline `const` block, see PR \
|
||||
#2920 <https://github.com/rust-lang/rfcs/pull/2920> \
|
||||
for more information",
|
||||
);
|
||||
}
|
||||
}
|
||||
ObligationCauseCode::VariableType(hir_id) => {
|
||||
let parent_node = self.tcx.hir().get_parent_node(hir_id);
|
||||
|
@ -10,6 +10,7 @@ use traits::{translate_substs, Reveal};
|
||||
|
||||
use tracing::debug;
|
||||
|
||||
#[instrument(level = "debug", skip(tcx))]
|
||||
fn resolve_instance<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>,
|
||||
@ -38,13 +39,13 @@ fn resolve_instance_of_const_arg<'tcx>(
|
||||
)
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(tcx))]
|
||||
fn inner_resolve_instance<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
key: ty::ParamEnvAnd<'tcx, (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>)>,
|
||||
) -> Result<Option<Instance<'tcx>>, ErrorReported> {
|
||||
let (param_env, (def, substs)) = key.into_parts();
|
||||
|
||||
debug!("resolve(def={:?}, substs={:?})", def.did, substs);
|
||||
let result = if let Some(trait_def_id) = tcx.trait_of_item(def.did) {
|
||||
debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env);
|
||||
let item = tcx.associated_item(def.did);
|
||||
@ -93,7 +94,7 @@ fn inner_resolve_instance<'tcx>(
|
||||
};
|
||||
Ok(Some(Instance { def, substs }))
|
||||
};
|
||||
debug!("resolve(def.did={:?}, substs={:?}) = {:?}", def.did, substs, result);
|
||||
debug!("inner_resolve_instance: result={:?}", result);
|
||||
result
|
||||
}
|
||||
|
||||
|
@ -649,12 +649,12 @@ impl<T> BTreeSet<T> {
|
||||
/// #![feature(map_first_last)]
|
||||
/// use std::collections::BTreeSet;
|
||||
///
|
||||
/// let mut map = BTreeSet::new();
|
||||
/// assert_eq!(map.first(), None);
|
||||
/// map.insert(1);
|
||||
/// assert_eq!(map.first(), Some(&1));
|
||||
/// map.insert(2);
|
||||
/// assert_eq!(map.first(), Some(&1));
|
||||
/// let mut set = BTreeSet::new();
|
||||
/// assert_eq!(set.first(), None);
|
||||
/// set.insert(1);
|
||||
/// assert_eq!(set.first(), Some(&1));
|
||||
/// set.insert(2);
|
||||
/// assert_eq!(set.first(), Some(&1));
|
||||
/// ```
|
||||
#[unstable(feature = "map_first_last", issue = "62924")]
|
||||
pub fn first(&self) -> Option<&T>
|
||||
@ -675,12 +675,12 @@ impl<T> BTreeSet<T> {
|
||||
/// #![feature(map_first_last)]
|
||||
/// use std::collections::BTreeSet;
|
||||
///
|
||||
/// let mut map = BTreeSet::new();
|
||||
/// assert_eq!(map.last(), None);
|
||||
/// map.insert(1);
|
||||
/// assert_eq!(map.last(), Some(&1));
|
||||
/// map.insert(2);
|
||||
/// assert_eq!(map.last(), Some(&2));
|
||||
/// let mut set = BTreeSet::new();
|
||||
/// assert_eq!(set.last(), None);
|
||||
/// set.insert(1);
|
||||
/// assert_eq!(set.last(), Some(&1));
|
||||
/// set.insert(2);
|
||||
/// assert_eq!(set.last(), Some(&2));
|
||||
/// ```
|
||||
#[unstable(feature = "map_first_last", issue = "62924")]
|
||||
pub fn last(&self) -> Option<&T>
|
||||
|
@ -401,8 +401,6 @@ impl<'a> Arguments<'a> {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(fmt_as_str)]
|
||||
///
|
||||
/// use std::fmt::Arguments;
|
||||
///
|
||||
/// fn write_str(_: &str) { /* ... */ }
|
||||
@ -417,13 +415,11 @@ impl<'a> Arguments<'a> {
|
||||
/// ```
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(fmt_as_str)]
|
||||
///
|
||||
/// assert_eq!(format_args!("hello").as_str(), Some("hello"));
|
||||
/// assert_eq!(format_args!("").as_str(), Some(""));
|
||||
/// assert_eq!(format_args!("{}", 1).as_str(), None);
|
||||
/// ```
|
||||
#[unstable(feature = "fmt_as_str", issue = "74442")]
|
||||
#[stable(feature = "fmt_as_str", since = "1.52.0")]
|
||||
#[inline]
|
||||
pub fn as_str(&self) -> Option<&'static str> {
|
||||
match (self.pieces, self.args) {
|
||||
|
@ -816,6 +816,7 @@ pub(crate) mod builtin {
|
||||
#[macro_export]
|
||||
macro_rules! env {
|
||||
($name:expr $(,)?) => {{ /* compiler built-in */ }};
|
||||
($name:expr, $error_msg:expr $(,)?) => {{ /* compiler built-in */ }};
|
||||
}
|
||||
|
||||
/// Optionally inspects an environment variable at compile time.
|
||||
|
@ -76,6 +76,10 @@ pub struct OsString {
|
||||
inner: Buf,
|
||||
}
|
||||
|
||||
/// Allows extension traits within `std`.
|
||||
#[unstable(feature = "sealed", issue = "none")]
|
||||
impl crate::sealed::Sealed for OsString {}
|
||||
|
||||
/// Borrowed reference to an OS string (see [`OsString`]).
|
||||
///
|
||||
/// This type represents a borrowed reference to a string in the operating system's preferred
|
||||
@ -100,6 +104,10 @@ pub struct OsStr {
|
||||
inner: Slice,
|
||||
}
|
||||
|
||||
/// Allows extension traits within `std`.
|
||||
#[unstable(feature = "sealed", issue = "none")]
|
||||
impl crate::sealed::Sealed for OsStr {}
|
||||
|
||||
impl OsString {
|
||||
/// Constructs a new empty `OsString`.
|
||||
///
|
||||
|
@ -264,7 +264,6 @@
|
||||
#![feature(exhaustive_patterns)]
|
||||
#![feature(extend_one)]
|
||||
#![feature(external_doc)]
|
||||
#![feature(fmt_as_str)]
|
||||
#![feature(fn_traits)]
|
||||
#![feature(format_args_nl)]
|
||||
#![feature(gen_future)]
|
||||
@ -582,3 +581,11 @@ include!("keyword_docs.rs");
|
||||
// is unconditional, so the unstable feature needs to be defined somewhere.
|
||||
#[unstable(feature = "restricted_std", issue = "none")]
|
||||
mod __restricted_std_workaround {}
|
||||
|
||||
mod sealed {
|
||||
/// This trait being unreachable from outside the crate
|
||||
/// prevents outside implementations of our extension traits.
|
||||
/// This allows adding more trait methods in the future.
|
||||
#[unstable(feature = "sealed", issue = "none")]
|
||||
pub trait Sealed {}
|
||||
}
|
||||
|
@ -408,7 +408,7 @@ impl<S: Stream> Stream for AssertUnwindSafe<S> {
|
||||
/// aborting the process as well. This function *only* catches unwinding panics,
|
||||
/// not those that abort the process.
|
||||
///
|
||||
/// Also note that unwinding into Rust code with a foreign exception (e.g. a
|
||||
/// Also note that unwinding into Rust code with a foreign exception (e.g.
|
||||
/// an exception thrown from C++ code) is undefined behavior.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -498,6 +498,10 @@ pub struct Command {
|
||||
inner: imp::Command,
|
||||
}
|
||||
|
||||
/// Allows extension traits within `std`.
|
||||
#[unstable(feature = "sealed", issue = "none")]
|
||||
impl crate::sealed::Sealed for Command {}
|
||||
|
||||
impl Command {
|
||||
/// Constructs a new `Command` for launching the program at
|
||||
/// path `program`, with the following default configuration:
|
||||
@ -1375,6 +1379,10 @@ impl From<fs::File> for Stdio {
|
||||
#[stable(feature = "process", since = "1.0.0")]
|
||||
pub struct ExitStatus(imp::ExitStatus);
|
||||
|
||||
/// Allows extension traits within `std`.
|
||||
#[unstable(feature = "sealed", issue = "none")]
|
||||
impl crate::sealed::Sealed for ExitStatus {}
|
||||
|
||||
impl ExitStatus {
|
||||
/// Was termination successful? Signal termination is not considered a
|
||||
/// success, and success is defined as a zero exit status.
|
||||
|
@ -6,20 +6,16 @@ use crate::ffi::OsStr;
|
||||
use crate::io;
|
||||
use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use crate::process;
|
||||
use crate::sealed::Sealed;
|
||||
use crate::sys;
|
||||
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
|
||||
|
||||
mod private {
|
||||
/// This trait being unreachable from outside the crate
|
||||
/// prevents other implementations of the `ExitStatusExt` trait,
|
||||
/// which allows potentially adding more trait methods in the future.
|
||||
#[stable(feature = "none", since = "1.51.0")]
|
||||
pub trait Sealed {}
|
||||
}
|
||||
|
||||
/// Unix-specific extensions to the [`process::Command`] builder.
|
||||
///
|
||||
/// This trait is sealed: it cannot be implemented outside the standard library.
|
||||
/// This is so that future additional methods are not breaking changes.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait CommandExt {
|
||||
pub trait CommandExt: Sealed {
|
||||
/// Sets the child process's user ID. This translates to a
|
||||
/// `setuid` call in the child process. Failure in the `setuid`
|
||||
/// call will cause the spawn to fail.
|
||||
@ -193,7 +189,7 @@ impl CommandExt for process::Command {
|
||||
/// This trait is sealed: it cannot be implemented outside the standard library.
|
||||
/// This is so that future additional methods are not breaking changes.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait ExitStatusExt: private::Sealed {
|
||||
pub trait ExitStatusExt: Sealed {
|
||||
/// Creates a new `ExitStatus` from the raw underlying `i32` return value of
|
||||
/// a process.
|
||||
#[stable(feature = "exit_status_from", since = "1.12.0")]
|
||||
@ -228,9 +224,6 @@ pub trait ExitStatusExt: private::Sealed {
|
||||
fn into_raw(self) -> i32;
|
||||
}
|
||||
|
||||
#[stable(feature = "none", since = "1.51.0")]
|
||||
impl private::Sealed for process::ExitStatus {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl ExitStatusExt for process::ExitStatus {
|
||||
fn from_raw(raw: i32) -> Self {
|
||||
|
@ -1023,7 +1023,7 @@ extern "system" {
|
||||
pub fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;
|
||||
|
||||
// >= Vista / Server 2008
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsymboliclinka
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createsymboliclinkw
|
||||
pub fn CreateSymbolicLinkW(
|
||||
lpSymlinkFileName: LPCWSTR,
|
||||
lpTargetFileName: LPCWSTR,
|
||||
|
@ -53,6 +53,7 @@
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::ffi::{OsStr, OsString};
|
||||
use crate::sealed::Sealed;
|
||||
use crate::sys::os_str::Buf;
|
||||
use crate::sys_common::wtf8::Wtf8Buf;
|
||||
use crate::sys_common::{AsInner, FromInner};
|
||||
@ -61,8 +62,11 @@ use crate::sys_common::{AsInner, FromInner};
|
||||
pub use crate::sys_common::wtf8::EncodeWide;
|
||||
|
||||
/// Windows-specific extensions to [`OsString`].
|
||||
///
|
||||
/// This trait is sealed: it cannot be implemented outside the standard library.
|
||||
/// This is so that future additional methods are not breaking changes.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait OsStringExt {
|
||||
pub trait OsStringExt: Sealed {
|
||||
/// Creates an `OsString` from a potentially ill-formed UTF-16 slice of
|
||||
/// 16-bit code units.
|
||||
///
|
||||
@ -92,8 +96,11 @@ impl OsStringExt for OsString {
|
||||
}
|
||||
|
||||
/// Windows-specific extensions to [`OsStr`].
|
||||
///
|
||||
/// This trait is sealed: it cannot be implemented outside the standard library.
|
||||
/// This is so that future additional methods are not breaking changes.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait OsStrExt {
|
||||
pub trait OsStrExt: Sealed {
|
||||
/// Re-encodes an `OsStr` as a wide character sequence, i.e., potentially
|
||||
/// ill-formed UTF-16.
|
||||
///
|
||||
|
@ -4,17 +4,10 @@
|
||||
|
||||
use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
|
||||
use crate::process;
|
||||
use crate::sealed::Sealed;
|
||||
use crate::sys;
|
||||
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
|
||||
|
||||
mod private {
|
||||
/// This trait being unreachable from outside the crate
|
||||
/// prevents other implementations of the `ExitStatusExt` trait,
|
||||
/// which allows potentially adding more trait methods in the future.
|
||||
#[stable(feature = "none", since = "1.51.0")]
|
||||
pub trait Sealed {}
|
||||
}
|
||||
|
||||
#[stable(feature = "process_extensions", since = "1.2.0")]
|
||||
impl FromRawHandle for process::Stdio {
|
||||
unsafe fn from_raw_handle(handle: RawHandle) -> process::Stdio {
|
||||
@ -85,7 +78,7 @@ impl IntoRawHandle for process::ChildStderr {
|
||||
/// This trait is sealed: it cannot be implemented outside the standard library.
|
||||
/// This is so that future additional methods are not breaking changes.
|
||||
#[stable(feature = "exit_status_from", since = "1.12.0")]
|
||||
pub trait ExitStatusExt: private::Sealed {
|
||||
pub trait ExitStatusExt: Sealed {
|
||||
/// Creates a new `ExitStatus` from the raw underlying `u32` return value of
|
||||
/// a process.
|
||||
#[stable(feature = "exit_status_from", since = "1.12.0")]
|
||||
@ -99,12 +92,12 @@ impl ExitStatusExt for process::ExitStatus {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "none", since = "1.51.0")]
|
||||
impl private::Sealed for process::ExitStatus {}
|
||||
|
||||
/// Windows-specific extensions to the [`process::Command`] builder.
|
||||
///
|
||||
/// This trait is sealed: it cannot be implemented outside the standard library.
|
||||
/// This is so that future additional methods are not breaking changes.
|
||||
#[stable(feature = "windows_process_extensions", since = "1.16.0")]
|
||||
pub trait CommandExt {
|
||||
pub trait CommandExt: Sealed {
|
||||
/// Sets the [process creation flags][1] to be passed to `CreateProcess`.
|
||||
///
|
||||
/// These will always be ORed with `CREATE_UNICODE_ENVIRONMENT`.
|
||||
|
@ -6,6 +6,7 @@ use crate::ffi::{OsStr, OsString};
|
||||
use crate::fmt;
|
||||
use crate::mem;
|
||||
use crate::rc::Rc;
|
||||
use crate::sealed::Sealed;
|
||||
use crate::str;
|
||||
use crate::sync::Arc;
|
||||
use crate::sys_common::bytestring::debug_fmt_bytestring;
|
||||
@ -232,8 +233,11 @@ impl Slice {
|
||||
}
|
||||
|
||||
/// Platform-specific extensions to [`OsString`].
|
||||
///
|
||||
/// This trait is sealed: it cannot be implemented outside the standard library.
|
||||
/// This is so that future additional methods are not breaking changes.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait OsStringExt {
|
||||
pub trait OsStringExt: Sealed {
|
||||
/// Creates an [`OsString`] from a byte vector.
|
||||
///
|
||||
/// See the module documentation for an example.
|
||||
@ -258,8 +262,11 @@ impl OsStringExt for OsString {
|
||||
}
|
||||
|
||||
/// Platform-specific extensions to [`OsStr`].
|
||||
///
|
||||
/// This trait is sealed: it cannot be implemented outside the standard library.
|
||||
/// This is so that future additional methods are not breaking changes.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait OsStrExt {
|
||||
pub trait OsStrExt: Sealed {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
/// Creates an [`OsStr`] from a byte slice.
|
||||
///
|
||||
|
@ -1,4 +1,5 @@
|
||||
This directory contains the source code of the rust project, including:
|
||||
|
||||
- The test suite
|
||||
- The bootstrapping build system
|
||||
- Various submodules for tools, like rustdoc, rls, etc.
|
||||
|
@ -579,8 +579,7 @@ impl<'a> Builder<'a> {
|
||||
self.run_step_descriptions(&Builder::get_step_descriptions(self.kind), &self.paths);
|
||||
}
|
||||
|
||||
pub fn default_doc(&self, paths: Option<&[PathBuf]>) {
|
||||
let paths = paths.unwrap_or(&[]);
|
||||
pub fn default_doc(&self, paths: &[PathBuf]) {
|
||||
self.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), paths);
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ impl Step for Docs {
|
||||
if !builder.config.docs {
|
||||
return None;
|
||||
}
|
||||
builder.default_doc(None);
|
||||
builder.default_doc(&[]);
|
||||
|
||||
let dest = "share/doc/rust/html";
|
||||
|
||||
@ -103,7 +103,7 @@ impl Step for RustcDocs {
|
||||
if !builder.config.compiler_docs {
|
||||
return None;
|
||||
}
|
||||
builder.default_doc(None);
|
||||
builder.default_doc(&[]);
|
||||
|
||||
let mut tarball = Tarball::new(builder, "rustc-docs", &host.triple);
|
||||
tarball.set_product_name("Rustc Documentation");
|
||||
|
@ -111,7 +111,7 @@ impl Step for Linkcheck {
|
||||
|
||||
builder.info(&format!("Linkcheck ({})", host));
|
||||
|
||||
builder.default_doc(None);
|
||||
builder.default_doc(&[]);
|
||||
|
||||
let _time = util::timeit(&builder);
|
||||
try_run(
|
||||
|
@ -300,7 +300,7 @@ flag][prefer-dynamic] may be used to influence which is used.
|
||||
If the same crate name is specified with and without a path, the one with the
|
||||
path is used and the pathless flag has no effect.
|
||||
|
||||
[extern prelude]: ../reference/items/extern-crates.html#extern-prelude
|
||||
[extern prelude]: ../reference/names/preludes.html#extern-prelude
|
||||
[prefer-dynamic]: codegen-options/index.md#prefer-dynamic
|
||||
|
||||
<a id="option-sysroot"></a>
|
||||
|
@ -1269,7 +1269,7 @@ impl Clean<Item> for ty::AssocItem {
|
||||
|
||||
AssocTypeItem(bounds, ty.clean(cx))
|
||||
} else {
|
||||
// FIXME: when could this happen? ASsociated items in inherent impls?
|
||||
// FIXME: when could this happen? Associated items in inherent impls?
|
||||
let type_ = cx.tcx.type_of(self.def_id).clean(cx);
|
||||
TypedefItem(
|
||||
Typedef {
|
||||
|
@ -91,6 +91,15 @@ pub unsafe fn sym_static() {
|
||||
asm!("adr r0, {}", sym extern_static);
|
||||
}
|
||||
|
||||
// Regression test for #82052.
|
||||
// CHECK-LABEL: issue_82052
|
||||
// CHECK: push {{.*}}lr
|
||||
// CHECK: @APP
|
||||
// CHECK: @NO_APP
|
||||
pub unsafe fn issue_82052() {
|
||||
asm!("", out("r14") _);
|
||||
}
|
||||
|
||||
macro_rules! check {
|
||||
($func:ident $ty:ident $class:ident $mov:literal) => {
|
||||
#[no_mangle]
|
||||
|
@ -0,0 +1,21 @@
|
||||
#![feature(const_generics, const_evaluatable_checked)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
// This test is a minimized reproduction for #79518 where
|
||||
// during error handling for the type mismatch we would try
|
||||
// to evaluate std::mem::size_of::<Self::Assoc> causing an ICE
|
||||
|
||||
trait Foo {
|
||||
type Assoc: PartialEq;
|
||||
const AssocInstance: Self::Assoc;
|
||||
|
||||
fn foo()
|
||||
where
|
||||
[(); std::mem::size_of::<Self::Assoc>()]: ,
|
||||
{
|
||||
Self::AssocInstance == [(); std::mem::size_of::<Self::Assoc>()];
|
||||
//~^ Error: mismatched types
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,14 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-79518-default_trait_method_normalization.rs:16:32
|
||||
|
|
||||
LL | Self::AssocInstance == [(); std::mem::size_of::<Self::Assoc>()];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found array `[(); _]`
|
||||
|
|
||||
= note: expected associated type `<Self as Foo>::Assoc`
|
||||
found array `[(); _]`
|
||||
= help: consider constraining the associated type `<Self as Foo>::Assoc` to `[(); _]` or calling a method that returns `<Self as Foo>::Assoc`
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -0,0 +1,24 @@
|
||||
// check-pass
|
||||
#![feature(const_generics, const_evaluatable_checked)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
// This tests that the correct `param_env` is used so that
|
||||
// attempting to normalize `Self::N` does not cause an ICE.
|
||||
|
||||
pub struct Foo<const N: usize>;
|
||||
|
||||
impl<const N: usize> Foo<N> {
|
||||
pub fn foo() {}
|
||||
}
|
||||
|
||||
pub trait Bar {
|
||||
const N: usize;
|
||||
fn bar()
|
||||
where
|
||||
[(); Self::N]: ,
|
||||
{
|
||||
Foo::<{ Self::N }>::foo();
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -7,6 +7,8 @@ LL | let _: [Option<Bar>; 2] = [no_copy(); 2];
|
||||
= help: the following implementations were found:
|
||||
<Option<T> as Copy>
|
||||
= note: the `Copy` trait is required because the repeated element will be copied
|
||||
= help: consider creating a new `const` item and initializing with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];`
|
||||
= help: create an inline `const` block, see PR #2920 <https://github.com/rust-lang/rfcs/pull/2920> for more information
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
7
src/test/ui/consts/const-fn-in-vec.rs
Normal file
7
src/test/ui/consts/const-fn-in-vec.rs
Normal file
@ -0,0 +1,7 @@
|
||||
fn main() {
|
||||
// should hint to create an inline `const` block
|
||||
// or to create a new `const` item
|
||||
let strings: [String; 5] = [String::new(); 5];
|
||||
//~^ ERROR the trait bound `String: Copy` is not satisfied
|
||||
println!("{:?}", strings);
|
||||
}
|
13
src/test/ui/consts/const-fn-in-vec.stderr
Normal file
13
src/test/ui/consts/const-fn-in-vec.stderr
Normal file
@ -0,0 +1,13 @@
|
||||
error[E0277]: the trait bound `String: Copy` is not satisfied
|
||||
--> $DIR/const-fn-in-vec.rs:4:32
|
||||
|
|
||||
LL | let strings: [String; 5] = [String::new(); 5];
|
||||
| ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
|
||||
|
|
||||
= note: the `Copy` trait is required because the repeated element will be copied
|
||||
= help: consider creating a new `const` item and initializing with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];`
|
||||
= help: create an inline `const` block, see PR #2920 <https://github.com/rust-lang/rfcs/pull/2920> for more information
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/issue-79690.rs:29:1
|
||||
|
|
||||
LL | const G: Fat = unsafe { Transmute { t: FOO }.u };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered read of part of a pointer at .1.<deref>.size.foo
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered (potentially part of) a pointer at .1.<deref>.size.foo, but expected plain (non-pointer) bytes
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
|
||||
|
||||
|
17
src/test/ui/pattern/usefulness/issue-72377.rs
Normal file
17
src/test/ui/pattern/usefulness/issue-72377.rs
Normal file
@ -0,0 +1,17 @@
|
||||
#[derive(PartialEq, Eq)]
|
||||
enum X { A, B, C, }
|
||||
|
||||
fn main() {
|
||||
let x = X::A;
|
||||
let y = Some(X::A);
|
||||
|
||||
match (x, y) {
|
||||
//~^ ERROR non-exhaustive patterns: `(A, Some(A))`, `(A, Some(B))`, `(B, Some(B))` and 2
|
||||
//~| more not covered
|
||||
(_, None) => false,
|
||||
(v, Some(w)) if v == w => true,
|
||||
(X::B, Some(X::C)) => false,
|
||||
(X::B, Some(X::A)) => false,
|
||||
(X::A, Some(X::C)) | (X::C, Some(X::A)) => false,
|
||||
};
|
||||
}
|
12
src/test/ui/pattern/usefulness/issue-72377.stderr
Normal file
12
src/test/ui/pattern/usefulness/issue-72377.stderr
Normal file
@ -0,0 +1,12 @@
|
||||
error[E0004]: non-exhaustive patterns: `(A, Some(A))`, `(A, Some(B))`, `(B, Some(B))` and 2 more not covered
|
||||
--> $DIR/issue-72377.rs:8:11
|
||||
|
|
||||
LL | match (x, y) {
|
||||
| ^^^^^^ patterns `(A, Some(A))`, `(A, Some(B))`, `(B, Some(B))` and 2 more not covered
|
||||
|
|
||||
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
|
||||
= note: the matched value is of type `(X, Option<X>)`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0004`.
|
@ -1 +1 @@
|
||||
Subproject commit 336909b63a14b801520c6627d90d750babcfe280
|
||||
Subproject commit 7435b9e98c9280043605748c11a1f450669e04d6
|
Loading…
Reference in New Issue
Block a user