mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-07 04:23:30 +00:00
Auto merge of #95552 - matthiaskrgr:rollup-bxminn9, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #95032 (Clean up, categorize and sort unstable features in std.) - #95260 (Better suggestions for `Fn`-family trait selection errors) - #95293 (suggest wrapping single-expr blocks in square brackets) - #95344 (Make `impl Debug for rustdoc::clean::Item` easier to read) - #95388 (interpret: make isize::MAX the limit for dynamic value sizes) - #95530 (rustdoc: do not show primitives and keywords as private) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
297a8018b5
@ -23,8 +23,8 @@ use rustc_target::abi::{call::FnAbi, Align, HasDataLayout, Size, TargetDataLayou
|
||||
|
||||
use super::{
|
||||
AllocCheck, AllocId, GlobalId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine,
|
||||
MemPlace, MemPlaceMeta, Memory, MemoryKind, Operand, Place, PlaceTy, Pointer, Provenance,
|
||||
Scalar, ScalarMaybeUninit, StackPopJump,
|
||||
MemPlace, MemPlaceMeta, Memory, MemoryKind, Operand, Place, PlaceTy, Pointer,
|
||||
PointerArithmetic, Provenance, Scalar, ScalarMaybeUninit, StackPopJump,
|
||||
};
|
||||
use crate::transform::validate::equal_up_to_regions;
|
||||
|
||||
@ -678,7 +678,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
let size = size.align_to(align);
|
||||
|
||||
// Check if this brought us over the size limit.
|
||||
if size.bytes() >= self.tcx.data_layout.obj_size_bound() {
|
||||
if size > self.max_size_of_val() {
|
||||
throw_ub!(InvalidMeta("total size is bigger than largest supported object"));
|
||||
}
|
||||
Ok(Some((size, align)))
|
||||
@ -694,9 +694,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
let elem = layout.field(self, 0);
|
||||
|
||||
// Make sure the slice is not too big.
|
||||
let size = elem.size.checked_mul(len, self).ok_or_else(|| {
|
||||
err_ub!(InvalidMeta("slice is bigger than largest supported object"))
|
||||
})?;
|
||||
let size = elem.size.bytes().saturating_mul(len); // we rely on `max_size_of_val` being smaller than `u64::MAX`.
|
||||
let size = Size::from_bytes(size);
|
||||
if size > self.max_size_of_val() {
|
||||
throw_ub!(InvalidMeta("slice is bigger than largest supported object"));
|
||||
}
|
||||
Ok(Some((size, elem.align.abi)))
|
||||
}
|
||||
|
||||
|
@ -531,7 +531,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
) -> InterpResult<'tcx, Pointer<Option<M::PointerTag>>> {
|
||||
// We cannot overflow i64 as a type's size must be <= isize::MAX.
|
||||
let pointee_size = i64::try_from(self.layout_of(pointee_ty)?.size.bytes()).unwrap();
|
||||
// The computed offset, in bytes, cannot overflow an isize.
|
||||
// The computed offset, in bytes, must not overflow an isize.
|
||||
// `checked_mul` enforces a too small bound, but no actual allocation can be big enough for
|
||||
// the difference to be noticeable.
|
||||
let offset_bytes =
|
||||
offset_count.checked_mul(pointee_size).ok_or(err_ub!(PointerArithOverflow))?;
|
||||
// The offset being in bounds cannot rely on "wrapping around" the address space.
|
||||
@ -563,6 +565,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
let count = self.read_scalar(&count)?.to_machine_usize(self)?;
|
||||
let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap().ty)?;
|
||||
let (size, align) = (layout.size, layout.align.abi);
|
||||
// `checked_mul` enforces a too small bound (the correct one would probably be machine_isize_max),
|
||||
// but no actual allocation can be big enough for the difference to be noticeable.
|
||||
let size = size.checked_mul(count, self).ok_or_else(|| {
|
||||
err_ub_format!(
|
||||
"overflow computing total size of `{}`",
|
||||
@ -588,6 +592,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
let byte = self.read_scalar(&byte)?.to_u8()?;
|
||||
let count = self.read_scalar(&count)?.to_machine_usize(self)?;
|
||||
|
||||
// `checked_mul` enforces a too small bound (the correct one would probably be machine_isize_max),
|
||||
// but no actual allocation can be big enough for the difference to be noticeable.
|
||||
let len = layout
|
||||
.size
|
||||
.checked_mul(count, self)
|
||||
|
@ -110,16 +110,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
.read_ptr_sized(pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES_SIZE).unwrap())?
|
||||
.check_init()?;
|
||||
let size = size.to_machine_usize(self)?;
|
||||
let size = Size::from_bytes(size);
|
||||
let align = vtable
|
||||
.read_ptr_sized(pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES_ALIGN).unwrap())?
|
||||
.check_init()?;
|
||||
let align = align.to_machine_usize(self)?;
|
||||
let align = Align::from_bytes(align).map_err(|e| err_ub!(InvalidVtableAlignment(e)))?;
|
||||
|
||||
if size >= self.tcx.data_layout.obj_size_bound() {
|
||||
if size > self.max_size_of_val() {
|
||||
throw_ub!(InvalidVtableSize);
|
||||
}
|
||||
Ok((Size::from_bytes(size), align))
|
||||
Ok((size, align))
|
||||
}
|
||||
|
||||
pub fn read_new_vtable_after_trait_upcasting_from_vtable(
|
||||
|
@ -1091,7 +1091,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
|
||||
/// Compares two given types, eliding parts that are the same between them and highlighting
|
||||
/// relevant differences, and return two representation of those types for highlighted printing.
|
||||
fn cmp(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> (DiagnosticStyledString, DiagnosticStyledString) {
|
||||
pub fn cmp(
|
||||
&self,
|
||||
t1: Ty<'tcx>,
|
||||
t2: Ty<'tcx>,
|
||||
) -> (DiagnosticStyledString, DiagnosticStyledString) {
|
||||
debug!("cmp(t1={}, t1.kind={:?}, t2={}, t2.kind={:?})", t1, t1.kind(), t2, t2.kind());
|
||||
|
||||
// helper functions
|
||||
|
@ -18,6 +18,11 @@ pub trait PointerArithmetic: HasDataLayout {
|
||||
self.data_layout().pointer_size
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn max_size_of_val(&self) -> Size {
|
||||
Size::from_bytes(self.machine_isize_max())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn machine_usize_max(&self) -> u64 {
|
||||
self.pointer_size().unsigned_int_max().try_into().unwrap()
|
||||
|
@ -119,9 +119,21 @@ impl<'tcx> ClosureKind {
|
||||
/// See `Ty::to_opt_closure_kind` for more details.
|
||||
pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
|
||||
match self {
|
||||
ty::ClosureKind::Fn => tcx.types.i8,
|
||||
ty::ClosureKind::FnMut => tcx.types.i16,
|
||||
ty::ClosureKind::FnOnce => tcx.types.i32,
|
||||
ClosureKind::Fn => tcx.types.i8,
|
||||
ClosureKind::FnMut => tcx.types.i16,
|
||||
ClosureKind::FnOnce => tcx.types.i32,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ClosureKind> {
|
||||
if Some(def_id) == tcx.lang_items().fn_once_trait() {
|
||||
Some(ClosureKind::FnOnce)
|
||||
} else if Some(def_id) == tcx.lang_items().fn_mut_trait() {
|
||||
Some(ClosureKind::FnMut)
|
||||
} else if Some(def_id) == tcx.lang_items().fn_trait() {
|
||||
Some(ClosureKind::Fn)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1919,17 +1919,13 @@ impl<'a> Parser<'a> {
|
||||
match snapshot.parse_array_or_repeat_expr(attrs, token::Brace) {
|
||||
Ok(arr) => {
|
||||
let hi = snapshot.prev_token.span;
|
||||
self.struct_span_err(
|
||||
arr.span,
|
||||
"this code is interpreted as a block expression, not an array",
|
||||
)
|
||||
.multipart_suggestion(
|
||||
"try using [] instead of {}",
|
||||
vec![(lo, "[".to_owned()), (hi, "]".to_owned())],
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.note("to define an array, one would use square brackets instead of curly braces")
|
||||
.emit();
|
||||
self.struct_span_err(arr.span, "this is a block expression, not an array")
|
||||
.multipart_suggestion(
|
||||
"to make an array, use square brackets instead of curly braces",
|
||||
vec![(lo, "[".to_owned()), (hi, "]".to_owned())],
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
|
||||
self.restore_snapshot(snapshot);
|
||||
Some(self.mk_expr_err(arr.span))
|
||||
|
@ -2,10 +2,10 @@ pub mod on_unimplemented;
|
||||
pub mod suggestions;
|
||||
|
||||
use super::{
|
||||
EvaluationResult, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes,
|
||||
Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedDirective,
|
||||
OnUnimplementedNote, OutputTypeParameterMismatch, Overflow, PredicateObligation,
|
||||
SelectionContext, SelectionError, TraitNotObjectSafe,
|
||||
EvaluationResult, FulfillmentContext, FulfillmentError, FulfillmentErrorCode,
|
||||
MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode,
|
||||
OnUnimplementedDirective, OnUnimplementedNote, OutputTypeParameterMismatch, Overflow,
|
||||
PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe,
|
||||
};
|
||||
|
||||
use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
|
||||
@ -21,6 +21,8 @@ use rustc_hir::intravisit::Visitor;
|
||||
use rustc_hir::GenericParam;
|
||||
use rustc_hir::Item;
|
||||
use rustc_hir::Node;
|
||||
use rustc_infer::infer::error_reporting::same_type_modulo_infer;
|
||||
use rustc_infer::traits::TraitEngine;
|
||||
use rustc_middle::thir::abstract_const::NotConstEvaluatable;
|
||||
use rustc_middle::traits::select::OverflowError;
|
||||
use rustc_middle::ty::error::ExpectedFound;
|
||||
@ -103,6 +105,17 @@ pub trait InferCtxtExt<'tcx> {
|
||||
found_args: Vec<ArgKind>,
|
||||
is_closure: bool,
|
||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
|
||||
|
||||
/// Checks if the type implements one of `Fn`, `FnMut`, or `FnOnce`
|
||||
/// in that order, and returns the generic type corresponding to the
|
||||
/// argument of that trait (corresponding to the closure arguments).
|
||||
fn type_implements_fn_trait(
|
||||
&self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
ty: ty::Binder<'tcx, Ty<'tcx>>,
|
||||
constness: ty::BoundConstness,
|
||||
polarity: ty::ImplPolarity,
|
||||
) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()>;
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
@ -563,7 +576,64 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
// Try to report a help message
|
||||
if !trait_ref.has_infer_types_or_consts()
|
||||
if is_fn_trait
|
||||
&& let Ok((implemented_kind, params)) = self.type_implements_fn_trait(
|
||||
obligation.param_env,
|
||||
trait_ref.self_ty(),
|
||||
trait_predicate.skip_binder().constness,
|
||||
trait_predicate.skip_binder().polarity,
|
||||
)
|
||||
{
|
||||
// If the type implements `Fn`, `FnMut`, or `FnOnce`, suppress the following
|
||||
// suggestion to add trait bounds for the type, since we only typically implement
|
||||
// these traits once.
|
||||
|
||||
// Note if the `FnMut` or `FnOnce` is less general than the trait we're trying
|
||||
// to implement.
|
||||
let selected_kind =
|
||||
ty::ClosureKind::from_def_id(self.tcx, trait_ref.def_id())
|
||||
.expect("expected to map DefId to ClosureKind");
|
||||
if !implemented_kind.extends(selected_kind) {
|
||||
err.note(
|
||||
&format!(
|
||||
"`{}` implements `{}`, but it must implement `{}`, which is more general",
|
||||
trait_ref.skip_binder().self_ty(),
|
||||
implemented_kind,
|
||||
selected_kind
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Note any argument mismatches
|
||||
let given_ty = params.skip_binder();
|
||||
let expected_ty = trait_ref.skip_binder().substs.type_at(1);
|
||||
if let ty::Tuple(given) = given_ty.kind()
|
||||
&& let ty::Tuple(expected) = expected_ty.kind()
|
||||
{
|
||||
if expected.len() != given.len() {
|
||||
// Note number of types that were expected and given
|
||||
err.note(
|
||||
&format!(
|
||||
"expected a closure taking {} argument{}, but one taking {} argument{} was given",
|
||||
given.len(),
|
||||
if given.len() == 1 { "" } else { "s" },
|
||||
expected.len(),
|
||||
if expected.len() == 1 { "" } else { "s" },
|
||||
)
|
||||
);
|
||||
} else if !same_type_modulo_infer(given_ty, expected_ty) {
|
||||
// Print type mismatch
|
||||
let (expected_args, given_args) =
|
||||
self.cmp(given_ty, expected_ty);
|
||||
err.note_expected_found(
|
||||
&"a closure with arguments",
|
||||
expected_args,
|
||||
&"a closure with arguments",
|
||||
given_args,
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if !trait_ref.has_infer_types_or_consts()
|
||||
&& self.predicate_can_apply(obligation.param_env, trait_ref)
|
||||
{
|
||||
// If a where-clause may be useful, remind the
|
||||
@ -1148,6 +1218,52 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
|
||||
err
|
||||
}
|
||||
|
||||
fn type_implements_fn_trait(
|
||||
&self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
ty: ty::Binder<'tcx, Ty<'tcx>>,
|
||||
constness: ty::BoundConstness,
|
||||
polarity: ty::ImplPolarity,
|
||||
) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()> {
|
||||
self.commit_if_ok(|_| {
|
||||
for trait_def_id in [
|
||||
self.tcx.lang_items().fn_trait(),
|
||||
self.tcx.lang_items().fn_mut_trait(),
|
||||
self.tcx.lang_items().fn_once_trait(),
|
||||
] {
|
||||
let Some(trait_def_id) = trait_def_id else { continue };
|
||||
// Make a fresh inference variable so we can determine what the substitutions
|
||||
// of the trait are.
|
||||
let var = self.next_ty_var(TypeVariableOrigin {
|
||||
span: DUMMY_SP,
|
||||
kind: TypeVariableOriginKind::MiscVariable,
|
||||
});
|
||||
let substs = self.tcx.mk_substs_trait(ty.skip_binder(), &[var.into()]);
|
||||
let obligation = Obligation::new(
|
||||
ObligationCause::dummy(),
|
||||
param_env,
|
||||
ty.rebind(ty::TraitPredicate {
|
||||
trait_ref: ty::TraitRef::new(trait_def_id, substs),
|
||||
constness,
|
||||
polarity,
|
||||
})
|
||||
.to_predicate(self.tcx),
|
||||
);
|
||||
let mut fulfill_cx = FulfillmentContext::new_in_snapshot();
|
||||
fulfill_cx.register_predicate_obligation(self, obligation);
|
||||
if fulfill_cx.select_all_or_error(self).is_empty() {
|
||||
return Ok((
|
||||
ty::ClosureKind::from_def_id(self.tcx, trait_def_id)
|
||||
.expect("expected to map DefId to ClosureKind"),
|
||||
ty.rebind(self.resolve_vars_if_possible(var)),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Err(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
trait InferCtxtPrivExt<'hir, 'tcx> {
|
||||
|
@ -39,6 +39,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
self.suggest_no_capture_closure(err, expected, expr_ty);
|
||||
self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty);
|
||||
self.suggest_missing_parentheses(err, expr);
|
||||
self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected);
|
||||
self.note_need_for_fn_pointer(err, expected, expr_ty);
|
||||
self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
|
||||
self.report_closure_inferred_return_type(err, expected);
|
||||
|
@ -774,57 +774,68 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let prev_diverges = self.diverges.get();
|
||||
let ctxt = BreakableCtxt { coerce: Some(coerce), may_break: false };
|
||||
|
||||
let (ctxt, ()) =
|
||||
self.with_breakable_ctxt(blk.hir_id, ctxt, || {
|
||||
for (pos, s) in blk.stmts.iter().enumerate() {
|
||||
self.check_stmt(s, blk.stmts.len() - 1 == pos);
|
||||
}
|
||||
let (ctxt, ()) = self.with_breakable_ctxt(blk.hir_id, ctxt, || {
|
||||
for (pos, s) in blk.stmts.iter().enumerate() {
|
||||
self.check_stmt(s, blk.stmts.len() - 1 == pos);
|
||||
}
|
||||
|
||||
// check the tail expression **without** holding the
|
||||
// `enclosing_breakables` lock below.
|
||||
let tail_expr_ty = tail_expr.map(|t| self.check_expr_with_expectation(t, expected));
|
||||
// check the tail expression **without** holding the
|
||||
// `enclosing_breakables` lock below.
|
||||
let tail_expr_ty = tail_expr.map(|t| self.check_expr_with_expectation(t, expected));
|
||||
|
||||
let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
|
||||
let ctxt = enclosing_breakables.find_breakable(blk.hir_id);
|
||||
let coerce = ctxt.coerce.as_mut().unwrap();
|
||||
if let Some(tail_expr_ty) = tail_expr_ty {
|
||||
let tail_expr = tail_expr.unwrap();
|
||||
let span = self.get_expr_coercion_span(tail_expr);
|
||||
let cause =
|
||||
self.cause(span, ObligationCauseCode::BlockTailExpression(blk.hir_id));
|
||||
coerce.coerce(self, &cause, tail_expr, tail_expr_ty);
|
||||
} else {
|
||||
// Subtle: if there is no explicit tail expression,
|
||||
// that is typically equivalent to a tail expression
|
||||
// of `()` -- except if the block diverges. In that
|
||||
// case, there is no value supplied from the tail
|
||||
// expression (assuming there are no other breaks,
|
||||
// this implies that the type of the block will be
|
||||
// `!`).
|
||||
//
|
||||
// #41425 -- label the implicit `()` as being the
|
||||
// "found type" here, rather than the "expected type".
|
||||
if !self.diverges.get().is_always() {
|
||||
// #50009 -- Do not point at the entire fn block span, point at the return type
|
||||
// span, as it is the cause of the requirement, and
|
||||
// `consider_hint_about_removing_semicolon` will point at the last expression
|
||||
// if it were a relevant part of the error. This improves usability in editors
|
||||
// that highlight errors inline.
|
||||
let mut sp = blk.span;
|
||||
let mut fn_span = None;
|
||||
if let Some((decl, ident)) = self.get_parent_fn_decl(blk.hir_id) {
|
||||
let ret_sp = decl.output.span();
|
||||
if let Some(block_sp) = self.parent_item_span(blk.hir_id) {
|
||||
// HACK: on some cases (`ui/liveness/liveness-issue-2163.rs`) the
|
||||
// output would otherwise be incorrect and even misleading. Make sure
|
||||
// the span we're aiming at correspond to a `fn` body.
|
||||
if block_sp == blk.span {
|
||||
sp = ret_sp;
|
||||
fn_span = Some(ident.span);
|
||||
}
|
||||
let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
|
||||
let ctxt = enclosing_breakables.find_breakable(blk.hir_id);
|
||||
let coerce = ctxt.coerce.as_mut().unwrap();
|
||||
if let Some(tail_expr_ty) = tail_expr_ty {
|
||||
let tail_expr = tail_expr.unwrap();
|
||||
let span = self.get_expr_coercion_span(tail_expr);
|
||||
let cause = self.cause(span, ObligationCauseCode::BlockTailExpression(blk.hir_id));
|
||||
let ty_for_diagnostic = coerce.merged_ty();
|
||||
// We use coerce_inner here because we want to augment the error
|
||||
// suggesting to wrap the block in square brackets if it might've
|
||||
// been mistaken array syntax
|
||||
coerce.coerce_inner(
|
||||
self,
|
||||
&cause,
|
||||
Some(tail_expr),
|
||||
tail_expr_ty,
|
||||
Some(&mut |diag: &mut Diagnostic| {
|
||||
self.suggest_block_to_brackets(diag, blk, tail_expr_ty, ty_for_diagnostic);
|
||||
}),
|
||||
false,
|
||||
);
|
||||
} else {
|
||||
// Subtle: if there is no explicit tail expression,
|
||||
// that is typically equivalent to a tail expression
|
||||
// of `()` -- except if the block diverges. In that
|
||||
// case, there is no value supplied from the tail
|
||||
// expression (assuming there are no other breaks,
|
||||
// this implies that the type of the block will be
|
||||
// `!`).
|
||||
//
|
||||
// #41425 -- label the implicit `()` as being the
|
||||
// "found type" here, rather than the "expected type".
|
||||
if !self.diverges.get().is_always() {
|
||||
// #50009 -- Do not point at the entire fn block span, point at the return type
|
||||
// span, as it is the cause of the requirement, and
|
||||
// `consider_hint_about_removing_semicolon` will point at the last expression
|
||||
// if it were a relevant part of the error. This improves usability in editors
|
||||
// that highlight errors inline.
|
||||
let mut sp = blk.span;
|
||||
let mut fn_span = None;
|
||||
if let Some((decl, ident)) = self.get_parent_fn_decl(blk.hir_id) {
|
||||
let ret_sp = decl.output.span();
|
||||
if let Some(block_sp) = self.parent_item_span(blk.hir_id) {
|
||||
// HACK: on some cases (`ui/liveness/liveness-issue-2163.rs`) the
|
||||
// output would otherwise be incorrect and even misleading. Make sure
|
||||
// the span we're aiming at correspond to a `fn` body.
|
||||
if block_sp == blk.span {
|
||||
sp = ret_sp;
|
||||
fn_span = Some(ident.span);
|
||||
}
|
||||
}
|
||||
coerce.coerce_forced_unit(
|
||||
}
|
||||
coerce.coerce_forced_unit(
|
||||
self,
|
||||
&self.misc(sp),
|
||||
&mut |err| {
|
||||
@ -837,21 +848,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// Our block must be a `assign desugar local; assignment`
|
||||
if let Some(hir::Node::Block(hir::Block {
|
||||
stmts:
|
||||
[hir::Stmt {
|
||||
kind:
|
||||
hir::StmtKind::Local(hir::Local {
|
||||
source: hir::LocalSource::AssignDesugar(_),
|
||||
..
|
||||
}),
|
||||
..
|
||||
}, hir::Stmt {
|
||||
kind:
|
||||
hir::StmtKind::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::Assign(..),
|
||||
..
|
||||
}),
|
||||
..
|
||||
}],
|
||||
[
|
||||
hir::Stmt {
|
||||
kind:
|
||||
hir::StmtKind::Local(hir::Local {
|
||||
source:
|
||||
hir::LocalSource::AssignDesugar(_),
|
||||
..
|
||||
}),
|
||||
..
|
||||
},
|
||||
hir::Stmt {
|
||||
kind:
|
||||
hir::StmtKind::Expr(hir::Expr {
|
||||
kind: hir::ExprKind::Assign(..),
|
||||
..
|
||||
}),
|
||||
..
|
||||
},
|
||||
],
|
||||
..
|
||||
})) = self.tcx.hir().find(blk.hir_id)
|
||||
{
|
||||
@ -871,9 +886,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
},
|
||||
false,
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if ctxt.may_break {
|
||||
// If we can break from the block, then the block's exit is always reachable
|
||||
|
@ -766,6 +766,77 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Given an expression type mismatch, peel any `&` expressions until we get to
|
||||
/// a block expression, and then suggest replacing the braces with square braces
|
||||
/// if it was possibly mistaken array syntax.
|
||||
pub(crate) fn suggest_block_to_brackets_peeling_refs(
|
||||
&self,
|
||||
diag: &mut Diagnostic,
|
||||
mut expr: &hir::Expr<'_>,
|
||||
mut expr_ty: Ty<'tcx>,
|
||||
mut expected_ty: Ty<'tcx>,
|
||||
) {
|
||||
loop {
|
||||
match (&expr.kind, expr_ty.kind(), expected_ty.kind()) {
|
||||
(
|
||||
hir::ExprKind::AddrOf(_, _, inner_expr),
|
||||
ty::Ref(_, inner_expr_ty, _),
|
||||
ty::Ref(_, inner_expected_ty, _),
|
||||
) => {
|
||||
expr = *inner_expr;
|
||||
expr_ty = *inner_expr_ty;
|
||||
expected_ty = *inner_expected_ty;
|
||||
}
|
||||
(hir::ExprKind::Block(blk, _), _, _) => {
|
||||
self.suggest_block_to_brackets(diag, *blk, expr_ty, expected_ty);
|
||||
break;
|
||||
}
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Suggest wrapping the block in square brackets instead of curly braces
|
||||
/// in case the block was mistaken array syntax, e.g. `{ 1 }` -> `[ 1 ]`.
|
||||
pub(crate) fn suggest_block_to_brackets(
|
||||
&self,
|
||||
diag: &mut Diagnostic,
|
||||
blk: &hir::Block<'_>,
|
||||
blk_ty: Ty<'tcx>,
|
||||
expected_ty: Ty<'tcx>,
|
||||
) {
|
||||
if let ty::Slice(elem_ty) | ty::Array(elem_ty, _) = expected_ty.kind() {
|
||||
if self.can_coerce(blk_ty, *elem_ty)
|
||||
&& blk.stmts.is_empty()
|
||||
&& blk.rules == hir::BlockCheckMode::DefaultBlock
|
||||
{
|
||||
let source_map = self.tcx.sess.source_map();
|
||||
if let Ok(snippet) = source_map.span_to_snippet(blk.span) {
|
||||
if snippet.starts_with('{') && snippet.ends_with('}') {
|
||||
diag.multipart_suggestion_verbose(
|
||||
"to create an array, use square brackets instead of curly braces",
|
||||
vec![
|
||||
(
|
||||
blk.span
|
||||
.shrink_to_lo()
|
||||
.with_hi(rustc_span::BytePos(blk.span.lo().0 + 1)),
|
||||
"[".to_string(),
|
||||
),
|
||||
(
|
||||
blk.span
|
||||
.shrink_to_hi()
|
||||
.with_lo(rustc_span::BytePos(blk.span.hi().0 - 1)),
|
||||
"]".to_string(),
|
||||
),
|
||||
],
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_loop(&self, id: hir::HirId) -> bool {
|
||||
let node = self.tcx.hir().get(id);
|
||||
matches!(node, Node::Expr(Expr { kind: ExprKind::Loop(..), .. }))
|
||||
|
@ -218,111 +218,122 @@
|
||||
feature(slice_index_methods, coerce_unsized, sgx_platform)
|
||||
)]
|
||||
#![deny(rustc::existing_doc_keyword)]
|
||||
// std is implemented with unstable features, many of which are internal
|
||||
// compiler details that will never be stable
|
||||
// NB: the following list is sorted to minimize merge conflicts.
|
||||
//
|
||||
// Language features:
|
||||
#![feature(alloc_error_handler)]
|
||||
#![feature(alloc_layout_extra)]
|
||||
#![feature(allocator_api)]
|
||||
#![feature(allocator_internals)]
|
||||
#![feature(allow_internal_unsafe)]
|
||||
#![feature(allow_internal_unstable)]
|
||||
#![feature(array_error_internals)]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(associated_type_bounds)]
|
||||
#![feature(async_iterator)]
|
||||
#![feature(atomic_mut_ptr)]
|
||||
#![feature(bench_black_box)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(c_unwind)]
|
||||
#![feature(c_variadic)]
|
||||
#![feature(cfg_accessible)]
|
||||
#![feature(cfg_eval)]
|
||||
#![feature(cfg_target_thread_local)]
|
||||
#![feature(char_error_internals)]
|
||||
#![feature(char_internals)]
|
||||
#![feature(concat_bytes)]
|
||||
#![feature(concat_idents)]
|
||||
#![cfg_attr(bootstrap, feature(const_fn_fn_ptr_basics))]
|
||||
#![cfg_attr(bootstrap, feature(const_fn_trait_bound))]
|
||||
#![feature(const_format_args)]
|
||||
#![feature(const_io_structs)]
|
||||
#![feature(const_ip)]
|
||||
#![feature(const_ipv4)]
|
||||
#![feature(const_ipv6)]
|
||||
#![feature(const_mut_refs)]
|
||||
#![feature(const_option)]
|
||||
#![feature(const_socketaddr)]
|
||||
#![feature(const_trait_impl)]
|
||||
#![feature(c_size_t)]
|
||||
#![feature(core_ffi_c)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(core_panic)]
|
||||
#![feature(custom_test_frameworks)]
|
||||
#![feature(decl_macro)]
|
||||
#![cfg_attr(not(bootstrap), feature(deprecated_suggestion))]
|
||||
#![feature(doc_cfg)]
|
||||
#![feature(doc_cfg_hide)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![cfg_attr(not(bootstrap), feature(deprecated_suggestion))]
|
||||
#![feature(doc_masked)]
|
||||
#![feature(doc_notable_trait)]
|
||||
#![feature(dropck_eyepatch)]
|
||||
#![feature(duration_checked_float)]
|
||||
#![feature(duration_constants)]
|
||||
#![feature(edition_panic)]
|
||||
#![feature(exact_size_is_empty)]
|
||||
#![feature(exhaustive_patterns)]
|
||||
#![feature(extend_one)]
|
||||
#![feature(float_minimum_maximum)]
|
||||
#![feature(format_args_nl)]
|
||||
#![feature(strict_provenance)]
|
||||
#![feature(get_mut_unchecked)]
|
||||
#![feature(hashmap_internals)]
|
||||
#![feature(int_error_internals)]
|
||||
#![feature(intra_doc_pointers)]
|
||||
#![feature(lang_items)]
|
||||
#![feature(linkage)]
|
||||
#![feature(log_syntax)]
|
||||
#![feature(map_try_insert)]
|
||||
#![feature(maybe_uninit_slice)]
|
||||
#![feature(maybe_uninit_write_slice)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(mixed_integer_ops)]
|
||||
#![feature(must_not_suspend)]
|
||||
#![feature(needs_panic_runtime)]
|
||||
#![feature(negative_impls)]
|
||||
#![feature(never_type)]
|
||||
#![feature(new_uninit)]
|
||||
#![feature(nll)]
|
||||
#![feature(platform_intrinsics)]
|
||||
#![feature(prelude_import)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(thread_local)]
|
||||
#![feature(try_blocks)]
|
||||
//
|
||||
// Library features (core):
|
||||
#![feature(array_error_internals)]
|
||||
#![feature(atomic_mut_ptr)]
|
||||
#![feature(char_error_internals)]
|
||||
#![feature(char_internals)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(duration_checked_float)]
|
||||
#![feature(duration_constants)]
|
||||
#![feature(exact_size_is_empty)]
|
||||
#![feature(extend_one)]
|
||||
#![feature(float_minimum_maximum)]
|
||||
#![feature(hashmap_internals)]
|
||||
#![feature(int_error_internals)]
|
||||
#![feature(maybe_uninit_slice)]
|
||||
#![feature(maybe_uninit_write_slice)]
|
||||
#![feature(mixed_integer_ops)]
|
||||
#![feature(nonnull_slice_from_raw_parts)]
|
||||
#![feature(once_cell)]
|
||||
#![feature(panic_can_unwind)]
|
||||
#![feature(panic_info_message)]
|
||||
#![feature(panic_internals)]
|
||||
#![feature(panic_can_unwind)]
|
||||
#![feature(panic_unwind)]
|
||||
#![feature(platform_intrinsics)]
|
||||
#![feature(portable_simd)]
|
||||
#![feature(prelude_import)]
|
||||
#![feature(ptr_as_uninit)]
|
||||
#![feature(raw_os_nonzero)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(saturating_int_impl)]
|
||||
#![feature(slice_internals)]
|
||||
#![feature(slice_ptr_get)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(std_internals)]
|
||||
#![feature(stdsimd)]
|
||||
#![feature(str_internals)]
|
||||
#![feature(test)]
|
||||
#![feature(thread_local)]
|
||||
#![feature(thread_local_internals)]
|
||||
#![feature(toowned_clone_into)]
|
||||
#![feature(strict_provenance)]
|
||||
#![feature(total_cmp)]
|
||||
#![feature(trace_macros)]
|
||||
#![feature(try_blocks)]
|
||||
//
|
||||
// Library features (alloc):
|
||||
#![feature(alloc_layout_extra)]
|
||||
#![feature(allocator_api)]
|
||||
#![feature(get_mut_unchecked)]
|
||||
#![feature(map_try_insert)]
|
||||
#![feature(new_uninit)]
|
||||
#![feature(toowned_clone_into)]
|
||||
#![feature(try_reserve_kind)]
|
||||
#![feature(vec_into_raw_parts)]
|
||||
// NB: the above list is sorted to minimize merge conflicts.
|
||||
//
|
||||
// Library features (unwind):
|
||||
#![feature(panic_unwind)]
|
||||
//
|
||||
// Only for re-exporting:
|
||||
#![feature(assert_matches)]
|
||||
#![feature(async_iterator)]
|
||||
#![feature(c_size_t)]
|
||||
#![feature(c_variadic)]
|
||||
#![feature(cfg_accessible)]
|
||||
#![feature(cfg_eval)]
|
||||
#![feature(concat_bytes)]
|
||||
#![feature(const_format_args)]
|
||||
#![feature(core_ffi_c)]
|
||||
#![feature(core_panic)]
|
||||
#![feature(custom_test_frameworks)]
|
||||
#![feature(edition_panic)]
|
||||
#![feature(format_args_nl)]
|
||||
#![feature(log_syntax)]
|
||||
#![feature(once_cell)]
|
||||
#![feature(saturating_int_impl)]
|
||||
#![feature(stdsimd)]
|
||||
#![feature(test)]
|
||||
#![feature(trace_macros)]
|
||||
//
|
||||
// Only used in tests/benchmarks:
|
||||
#![feature(bench_black_box)]
|
||||
//
|
||||
// Only for const-ness:
|
||||
#![feature(const_io_structs)]
|
||||
#![feature(const_ip)]
|
||||
#![feature(const_ipv4)]
|
||||
#![feature(const_ipv6)]
|
||||
#![feature(const_option)]
|
||||
#![feature(const_socketaddr)]
|
||||
#![feature(thread_local_internals)]
|
||||
//
|
||||
#![default_lib_allocator]
|
||||
|
||||
// Explicitly import the prelude. The compiler uses this same unstable attribute
|
||||
|
@ -1,5 +1,6 @@
|
||||
use std::cell::RefCell;
|
||||
use std::default::Default;
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
use std::iter;
|
||||
use std::lazy::SyncOnceCell as OnceCell;
|
||||
@ -355,7 +356,7 @@ crate enum ExternalLocation {
|
||||
/// Anything with a source location and set of attributes and, optionally, a
|
||||
/// name. That is, anything that can be documented. This doesn't correspond
|
||||
/// directly to the AST's concept of an item; it's a strict superset.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone)]
|
||||
crate struct Item {
|
||||
/// The name of this item.
|
||||
/// Optional because not every item has a name, e.g. impls.
|
||||
@ -370,6 +371,27 @@ crate struct Item {
|
||||
crate cfg: Option<Arc<Cfg>>,
|
||||
}
|
||||
|
||||
/// NOTE: this does NOT unconditionally print every item, to avoid thousands of lines of logs.
|
||||
/// If you want to see the debug output for attributes and the `kind` as well, use `{:#?}` instead of `{:?}`.
|
||||
impl fmt::Debug for Item {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let alternate = f.alternate();
|
||||
// hand-picked fields that don't bloat the logs too much
|
||||
let mut fmt = f.debug_struct("Item");
|
||||
fmt.field("name", &self.name)
|
||||
.field("visibility", &self.visibility)
|
||||
.field("def_id", &self.def_id);
|
||||
// allow printing the full item if someone really wants to
|
||||
if alternate {
|
||||
fmt.field("attrs", &self.attrs).field("kind", &self.kind).field("cfg", &self.cfg);
|
||||
} else {
|
||||
fmt.field("kind", &self.type_());
|
||||
fmt.field("docs", &self.doc_value());
|
||||
}
|
||||
fmt.finish()
|
||||
}
|
||||
}
|
||||
|
||||
// `Item` is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||
rustc_data_structures::static_assert_size!(Item, 56);
|
||||
@ -471,14 +493,17 @@ impl Item {
|
||||
) -> Item {
|
||||
trace!("name={:?}, def_id={:?}", name, def_id);
|
||||
|
||||
Item {
|
||||
def_id: def_id.into(),
|
||||
kind: box kind,
|
||||
name,
|
||||
attrs,
|
||||
visibility: cx.tcx.visibility(def_id).clean(cx),
|
||||
cfg,
|
||||
}
|
||||
// Primitives and Keywords are written in the source code as private modules.
|
||||
// The modules need to be private so that nobody actually uses them, but the
|
||||
// keywords and primitives that they are documenting are public.
|
||||
let visibility = if matches!(&kind, ItemKind::KeywordItem(..) | ItemKind::PrimitiveItem(..))
|
||||
{
|
||||
Visibility::Public
|
||||
} else {
|
||||
cx.tcx.visibility(def_id).clean(cx)
|
||||
};
|
||||
|
||||
Item { def_id: def_id.into(), kind: box kind, name, attrs, visibility, cfg }
|
||||
}
|
||||
|
||||
/// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
|
||||
|
@ -12,6 +12,7 @@
|
||||
// @has foo/index.html '//a/@href' '../foo/index.html'
|
||||
// @!has foo/foo/index.html
|
||||
// @!has-dir foo/foo
|
||||
// @!has foo/index.html '//span' '🔒'
|
||||
#[doc(keyword = "match")]
|
||||
/// this is a test!
|
||||
mod foo{}
|
||||
|
21
src/test/rustdoc/primitive.rs
Normal file
21
src/test/rustdoc/primitive.rs
Normal file
@ -0,0 +1,21 @@
|
||||
#![crate_name = "foo"]
|
||||
|
||||
#![feature(rustdoc_internals)]
|
||||
|
||||
// @has foo/index.html '//h2[@id="primitives"]' 'Primitive Types'
|
||||
// @has foo/index.html '//a[@href="primitive.i32.html"]' 'i32'
|
||||
// @has foo/index.html '//div[@class="sidebar-elems"]//li/a' 'Primitive Types'
|
||||
// @has foo/index.html '//div[@class="sidebar-elems"]//li/a/@href' '#primitives'
|
||||
// @has foo/primitive.i32.html '//a[@class="primitive"]' 'i32'
|
||||
// @has foo/primitive.i32.html '//span[@class="in-band"]' 'Primitive Type i32'
|
||||
// @has foo/primitive.i32.html '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
|
||||
// @has foo/index.html '//a/@href' '../foo/index.html'
|
||||
// @!has foo/index.html '//span' '🔒'
|
||||
#[doc(primitive = "i32")]
|
||||
/// this is a test!
|
||||
mod i32{}
|
||||
|
||||
// @has foo/primitive.bool.html '//section[@id="main-content"]//div[@class="docblock"]//p' 'hello'
|
||||
#[doc(primitive = "bool")]
|
||||
/// hello
|
||||
mod bool {}
|
@ -104,6 +104,17 @@ LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:71:1
|
||||
|
|
||||
LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid reference metadata: slice is bigger than largest supported object
|
||||
|
|
||||
= 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.
|
||||
= note: the raw bytes of the constant (size: 8, align: 4) {
|
||||
╾─allocN─╼ ff ff ff 7f │ ╾──╼....
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:74:1
|
||||
|
|
||||
LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
|
||||
|
|
||||
@ -113,7 +124,7 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:74:1
|
||||
--> $DIR/ub-wide-ptr.rs:77:1
|
||||
|
|
||||
LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (going beyond the bounds of its allocation)
|
||||
@ -124,7 +135,7 @@ LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999us
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:77:1
|
||||
--> $DIR/ub-wide-ptr.rs:80:1
|
||||
|
|
||||
LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
|
||||
@ -135,7 +146,7 @@ LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:81:1
|
||||
--> $DIR/ub-wide-ptr.rs:84:1
|
||||
|
|
||||
LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>[0]: encountered 0x03, but expected a boolean
|
||||
@ -146,29 +157,29 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:87:1
|
||||
--> $DIR/ub-wide-ptr.rs:90:1
|
||||
|
|
||||
LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.0: encountered 0x03, but expected a boolean
|
||||
|
|
||||
= 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.
|
||||
= note: the raw bytes of the constant (size: 4, align: 4) {
|
||||
╾─allocN─╼ │ ╾──╼
|
||||
╾allocN─╼ │ ╾──╼
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:90:1
|
||||
--> $DIR/ub-wide-ptr.rs:93:1
|
||||
|
|
||||
LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.1[0]: encountered 0x03, but expected a boolean
|
||||
|
|
||||
= 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.
|
||||
= note: the raw bytes of the constant (size: 4, align: 4) {
|
||||
╾─allocN─╼ │ ╾──╼
|
||||
╾allocN─╼ │ ╾──╼
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:97:1
|
||||
--> $DIR/ub-wide-ptr.rs:100:1
|
||||
|
|
||||
LL | / const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
|
||||
LL | |
|
||||
@ -183,7 +194,7 @@ LL | | };
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:105:1
|
||||
--> $DIR/ub-wide-ptr.rs:108:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered too small vtable
|
||||
@ -194,7 +205,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:108:1
|
||||
--> $DIR/ub-wide-ptr.rs:111:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered too small vtable
|
||||
@ -205,7 +216,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:111:1
|
||||
--> $DIR/ub-wide-ptr.rs:114:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered dangling vtable pointer in wide pointer
|
||||
@ -216,7 +227,7 @@ LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:113:1
|
||||
--> $DIR/ub-wide-ptr.rs:116:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered unaligned vtable pointer in wide pointer
|
||||
@ -227,7 +238,7 @@ LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:115:1
|
||||
--> $DIR/ub-wide-ptr.rs:118:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function)
|
||||
@ -238,7 +249,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:117:1
|
||||
--> $DIR/ub-wide-ptr.rs:120:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function)
|
||||
@ -249,7 +260,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:119:1
|
||||
--> $DIR/ub-wide-ptr.rs:122:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered invalid drop function pointer in vtable (not pointing to a function)
|
||||
@ -260,7 +271,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::trans
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:123:1
|
||||
--> $DIR/ub-wide-ptr.rs:126:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
|
||||
@ -271,7 +282,7 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_,
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:127:1
|
||||
--> $DIR/ub-wide-ptr.rs:130:1
|
||||
|
|
||||
LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling vtable pointer in wide pointer
|
||||
@ -282,7 +293,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:129:1
|
||||
--> $DIR/ub-wide-ptr.rs:132:1
|
||||
|
|
||||
LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too small vtable
|
||||
@ -293,17 +304,17 @@ LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transm
|
||||
}
|
||||
|
||||
error[E0080]: could not evaluate static initializer
|
||||
--> $DIR/ub-wide-ptr.rs:135:5
|
||||
--> $DIR/ub-wide-ptr.rs:138:5
|
||||
|
|
||||
LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is not a valid pointer
|
||||
|
||||
error[E0080]: could not evaluate static initializer
|
||||
--> $DIR/ub-wide-ptr.rs:139:5
|
||||
--> $DIR/ub-wide-ptr.rs:142:5
|
||||
|
|
||||
LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: allocN has size N, so pointer to 12 bytes starting at offset N is out-of-bounds
|
||||
|
||||
error: aborting due to 28 previous errors
|
||||
error: aborting due to 29 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
||||
|
@ -104,6 +104,17 @@ LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:71:1
|
||||
|
|
||||
LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid reference metadata: slice is bigger than largest supported object
|
||||
|
|
||||
= 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.
|
||||
= note: the raw bytes of the constant (size: 16, align: 8) {
|
||||
╾───────allocN───────╼ ff ff ff ff ff ff ff 7f │ ╾──────╼........
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:74:1
|
||||
|
|
||||
LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
|
||||
|
|
||||
@ -113,7 +124,7 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:74:1
|
||||
--> $DIR/ub-wide-ptr.rs:77:1
|
||||
|
|
||||
LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (going beyond the bounds of its allocation)
|
||||
@ -124,7 +135,7 @@ LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999us
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:77:1
|
||||
--> $DIR/ub-wide-ptr.rs:80:1
|
||||
|
|
||||
LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
|
||||
@ -135,7 +146,7 @@ LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:81:1
|
||||
--> $DIR/ub-wide-ptr.rs:84:1
|
||||
|
|
||||
LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>[0]: encountered 0x03, but expected a boolean
|
||||
@ -146,29 +157,29 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:87:1
|
||||
--> $DIR/ub-wide-ptr.rs:90:1
|
||||
|
|
||||
LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.0: encountered 0x03, but expected a boolean
|
||||
|
|
||||
= 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.
|
||||
= note: the raw bytes of the constant (size: 8, align: 8) {
|
||||
╾───────allocN───────╼ │ ╾──────╼
|
||||
╾──────allocN───────╼ │ ╾──────╼
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:90:1
|
||||
--> $DIR/ub-wide-ptr.rs:93:1
|
||||
|
|
||||
LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.1[0]: encountered 0x03, but expected a boolean
|
||||
|
|
||||
= 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.
|
||||
= note: the raw bytes of the constant (size: 8, align: 8) {
|
||||
╾───────allocN───────╼ │ ╾──────╼
|
||||
╾──────allocN───────╼ │ ╾──────╼
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:97:1
|
||||
--> $DIR/ub-wide-ptr.rs:100:1
|
||||
|
|
||||
LL | / const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
|
||||
LL | |
|
||||
@ -183,7 +194,7 @@ LL | | };
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:105:1
|
||||
--> $DIR/ub-wide-ptr.rs:108:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered too small vtable
|
||||
@ -194,7 +205,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:108:1
|
||||
--> $DIR/ub-wide-ptr.rs:111:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered too small vtable
|
||||
@ -205,7 +216,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:111:1
|
||||
--> $DIR/ub-wide-ptr.rs:114:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered dangling vtable pointer in wide pointer
|
||||
@ -216,7 +227,7 @@ LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:113:1
|
||||
--> $DIR/ub-wide-ptr.rs:116:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered unaligned vtable pointer in wide pointer
|
||||
@ -227,7 +238,7 @@ LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:115:1
|
||||
--> $DIR/ub-wide-ptr.rs:118:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function)
|
||||
@ -238,7 +249,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:117:1
|
||||
--> $DIR/ub-wide-ptr.rs:120:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function)
|
||||
@ -249,7 +260,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:119:1
|
||||
--> $DIR/ub-wide-ptr.rs:122:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered invalid drop function pointer in vtable (not pointing to a function)
|
||||
@ -260,7 +271,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::trans
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:123:1
|
||||
--> $DIR/ub-wide-ptr.rs:126:1
|
||||
|
|
||||
LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
|
||||
@ -271,7 +282,7 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_,
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:127:1
|
||||
--> $DIR/ub-wide-ptr.rs:130:1
|
||||
|
|
||||
LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling vtable pointer in wide pointer
|
||||
@ -282,7 +293,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/ub-wide-ptr.rs:129:1
|
||||
--> $DIR/ub-wide-ptr.rs:132:1
|
||||
|
|
||||
LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too small vtable
|
||||
@ -293,17 +304,17 @@ LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transm
|
||||
}
|
||||
|
||||
error[E0080]: could not evaluate static initializer
|
||||
--> $DIR/ub-wide-ptr.rs:135:5
|
||||
--> $DIR/ub-wide-ptr.rs:138:5
|
||||
|
|
||||
LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is not a valid pointer
|
||||
|
||||
error[E0080]: could not evaluate static initializer
|
||||
--> $DIR/ub-wide-ptr.rs:139:5
|
||||
--> $DIR/ub-wide-ptr.rs:142:5
|
||||
|
|
||||
LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: allocN has size N, so pointer to 24 bytes starting at offset N is out-of-bounds
|
||||
|
||||
error: aborting due to 28 previous errors
|
||||
error: aborting due to 29 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
||||
|
@ -67,6 +67,9 @@ const SLICE_LENGTH_UNINIT: &[u8] = unsafe {
|
||||
// bad slice: length too big
|
||||
const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
// bad slice: length computation overflows
|
||||
const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) };
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
// bad slice: length not an int
|
||||
const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
|
@ -2,8 +2,9 @@
|
||||
|
||||
#![feature(const_size_of_val, const_align_of_val)]
|
||||
#![feature(const_size_of_val_raw, const_align_of_val_raw, layout_for_ptr)]
|
||||
#![feature(const_slice_from_raw_parts)]
|
||||
|
||||
use std::mem;
|
||||
use std::{mem, ptr};
|
||||
|
||||
struct Foo(u32);
|
||||
|
||||
@ -34,6 +35,8 @@ const ALIGN_OF_UGH: usize = mem::align_of_val(&UGH);
|
||||
const SIZE_OF_SLICE: usize = mem::size_of_val("foobar".as_bytes());
|
||||
|
||||
const SIZE_OF_DANGLING: usize = unsafe { mem::size_of_val_raw(0x100 as *const i32) };
|
||||
const SIZE_OF_BIG: usize =
|
||||
unsafe { mem::size_of_val_raw(ptr::slice_from_raw_parts(0 as *const u8, isize::MAX as usize)) };
|
||||
const ALIGN_OF_DANGLING: usize = unsafe { mem::align_of_val_raw(0x100 as *const i16) };
|
||||
|
||||
fn main() {
|
||||
@ -46,6 +49,7 @@ fn main() {
|
||||
assert_eq!(ALIGN_OF_UGH, mem::align_of::<Ugh>());
|
||||
|
||||
assert_eq!(SIZE_OF_DANGLING, mem::size_of::<i32>());
|
||||
assert_eq!(SIZE_OF_BIG, isize::MAX as usize);
|
||||
assert_eq!(ALIGN_OF_DANGLING, mem::align_of::<i16>());
|
||||
|
||||
assert_eq!(SIZE_OF_SLICE, "foobar".len());
|
||||
|
@ -0,0 +1,10 @@
|
||||
const A: [&str; 1] = { "hello" };
|
||||
//~^ ERROR mismatched types
|
||||
|
||||
const B: &[u32] = &{ 1 };
|
||||
//~^ ERROR mismatched types
|
||||
|
||||
const C: &&[u32; 1] = &&{ 1 };
|
||||
//~^ ERROR mismatched types
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,38 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/brackets-to-braces-single-element.rs:1:24
|
||||
|
|
||||
LL | const A: [&str; 1] = { "hello" };
|
||||
| ^^^^^^^ expected array `[&'static str; 1]`, found `&str`
|
||||
|
|
||||
help: to create an array, use square brackets instead of curly braces
|
||||
|
|
||||
LL | const A: [&str; 1] = [ "hello" ];
|
||||
| ~ ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/brackets-to-braces-single-element.rs:4:19
|
||||
|
|
||||
LL | const B: &[u32] = &{ 1 };
|
||||
| ^^^^^^ expected slice `[u32]`, found integer
|
||||
|
|
||||
= note: expected reference `&'static [u32]`
|
||||
found reference `&{integer}`
|
||||
help: to create an array, use square brackets instead of curly braces
|
||||
|
|
||||
LL | const B: &[u32] = &[ 1 ];
|
||||
| ~ ~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/brackets-to-braces-single-element.rs:7:27
|
||||
|
|
||||
LL | const C: &&[u32; 1] = &&{ 1 };
|
||||
| ^ expected array `[u32; 1]`, found integer
|
||||
|
|
||||
help: to create an array, use square brackets instead of curly braces
|
||||
|
|
||||
LL | const C: &&[u32; 1] = &&[ 1 ];
|
||||
| ~ ~
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -1,15 +1,16 @@
|
||||
fn main() {}
|
||||
|
||||
const FOO: [u8; 3] = { //~ ERROR this code is interpreted as a block expression
|
||||
const FOO: [u8; 3] = {
|
||||
//~^ ERROR this is a block expression, not an array
|
||||
1, 2, 3
|
||||
};
|
||||
|
||||
const BAR: [&str; 3] = {"one", "two", "three"};
|
||||
//~^ ERROR this code is interpreted as a block expression
|
||||
//~^ ERROR this is a block expression, not an array
|
||||
|
||||
fn foo() {
|
||||
{1, 2, 3};
|
||||
//~^ ERROR this code is interpreted as a block expression
|
||||
//~^ ERROR this is a block expression, not an array
|
||||
}
|
||||
|
||||
fn bar() {
|
||||
|
@ -1,46 +1,45 @@
|
||||
error: this code is interpreted as a block expression, not an array
|
||||
error: this is a block expression, not an array
|
||||
--> $DIR/issue-87830-try-brackets-for-arrays.rs:3:22
|
||||
|
|
||||
LL | const FOO: [u8; 3] = {
|
||||
| ______________________^
|
||||
LL | |
|
||||
LL | | 1, 2, 3
|
||||
LL | | };
|
||||
| |_^
|
||||
|
|
||||
= note: to define an array, one would use square brackets instead of curly braces
|
||||
help: try using [] instead of {}
|
||||
help: to make an array, use square brackets instead of curly braces
|
||||
|
|
||||
LL ~ const FOO: [u8; 3] = [
|
||||
LL |
|
||||
LL | 1, 2, 3
|
||||
LL ~ ];
|
||||
|
|
||||
|
||||
error: this code is interpreted as a block expression, not an array
|
||||
--> $DIR/issue-87830-try-brackets-for-arrays.rs:7:24
|
||||
error: this is a block expression, not an array
|
||||
--> $DIR/issue-87830-try-brackets-for-arrays.rs:8:24
|
||||
|
|
||||
LL | const BAR: [&str; 3] = {"one", "two", "three"};
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: to define an array, one would use square brackets instead of curly braces
|
||||
help: try using [] instead of {}
|
||||
help: to make an array, use square brackets instead of curly braces
|
||||
|
|
||||
LL | const BAR: [&str; 3] = ["one", "two", "three"];
|
||||
| ~ ~
|
||||
|
||||
error: this code is interpreted as a block expression, not an array
|
||||
--> $DIR/issue-87830-try-brackets-for-arrays.rs:11:5
|
||||
error: this is a block expression, not an array
|
||||
--> $DIR/issue-87830-try-brackets-for-arrays.rs:12:5
|
||||
|
|
||||
LL | {1, 2, 3};
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: to define an array, one would use square brackets instead of curly braces
|
||||
help: try using [] instead of {}
|
||||
help: to make an array, use square brackets instead of curly braces
|
||||
|
|
||||
LL | [1, 2, 3];
|
||||
| ~ ~
|
||||
|
||||
error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
|
||||
--> $DIR/issue-87830-try-brackets-for-arrays.rs:16:6
|
||||
--> $DIR/issue-87830-try-brackets-for-arrays.rs:17:6
|
||||
|
|
||||
LL | 1, 2, 3
|
||||
| ^ expected one of `.`, `;`, `?`, `}`, or an operator
|
||||
|
@ -4,6 +4,8 @@ error[E0277]: expected a `Fn<(<_ as ATC<'a>>::Type,)>` closure, found `F`
|
||||
LL | call(f, ());
|
||||
| ^^^^ expected an `Fn<(<_ as ATC<'a>>::Type,)>` closure, found `F`
|
||||
|
|
||||
= note: expected a closure with arguments `((),)`
|
||||
found a closure with arguments `(<_ as ATC<'a>>::Type,)`
|
||||
note: required by a bound in `call`
|
||||
--> $DIR/issue-62529-3.rs:9:36
|
||||
|
|
||||
|
@ -7,6 +7,8 @@ LL | let t8 = t8n(t7, t7p(f, g));
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `Fn<(_,)>` is not implemented for `impl Fn(((_, _), _))`
|
||||
= note: expected a closure with arguments `(((_, _), _),)`
|
||||
found a closure with arguments `(_,)`
|
||||
note: required by a bound in `t8n`
|
||||
--> $DIR/issue-59494.rs:5:45
|
||||
|
|
||||
|
28
src/test/ui/trait-bounds/mismatch-fn-trait.rs
Normal file
28
src/test/ui/trait-bounds/mismatch-fn-trait.rs
Normal file
@ -0,0 +1,28 @@
|
||||
fn take(_f: impl FnMut(i32)) {}
|
||||
|
||||
fn test1(f: impl FnMut(u32)) {
|
||||
take(f)
|
||||
//~^ ERROR [E0277]
|
||||
}
|
||||
|
||||
fn test2(f: impl FnMut(i32, i32)) {
|
||||
take(f)
|
||||
//~^ ERROR [E0277]
|
||||
}
|
||||
|
||||
fn test3(f: impl FnMut()) {
|
||||
take(f)
|
||||
//~^ ERROR [E0277]
|
||||
}
|
||||
|
||||
fn test4(f: impl FnOnce(i32)) {
|
||||
take(f)
|
||||
//~^ ERROR [E0277]
|
||||
}
|
||||
|
||||
fn test5(f: impl FnOnce(u32)) {
|
||||
take(f)
|
||||
//~^ ERROR [E0277]
|
||||
}
|
||||
|
||||
fn main() {}
|
81
src/test/ui/trait-bounds/mismatch-fn-trait.stderr
Normal file
81
src/test/ui/trait-bounds/mismatch-fn-trait.stderr
Normal file
@ -0,0 +1,81 @@
|
||||
error[E0277]: expected a `FnMut<(i32,)>` closure, found `impl FnMut(u32)`
|
||||
--> $DIR/mismatch-fn-trait.rs:4:10
|
||||
|
|
||||
LL | take(f)
|
||||
| ---- ^ expected an `FnMut<(i32,)>` closure, found `impl FnMut(u32)`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: expected a closure with arguments `(u32,)`
|
||||
found a closure with arguments `(i32,)`
|
||||
note: required by a bound in `take`
|
||||
--> $DIR/mismatch-fn-trait.rs:1:18
|
||||
|
|
||||
LL | fn take(_f: impl FnMut(i32)) {}
|
||||
| ^^^^^^^^^^ required by this bound in `take`
|
||||
|
||||
error[E0277]: expected a `FnMut<(i32,)>` closure, found `impl FnMut(i32, i32)`
|
||||
--> $DIR/mismatch-fn-trait.rs:9:10
|
||||
|
|
||||
LL | take(f)
|
||||
| ---- ^ expected an `FnMut<(i32,)>` closure, found `impl FnMut(i32, i32)`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: expected a closure taking 2 arguments, but one taking 1 argument was given
|
||||
note: required by a bound in `take`
|
||||
--> $DIR/mismatch-fn-trait.rs:1:18
|
||||
|
|
||||
LL | fn take(_f: impl FnMut(i32)) {}
|
||||
| ^^^^^^^^^^ required by this bound in `take`
|
||||
|
||||
error[E0277]: expected a `FnMut<(i32,)>` closure, found `impl FnMut()`
|
||||
--> $DIR/mismatch-fn-trait.rs:14:10
|
||||
|
|
||||
LL | take(f)
|
||||
| ---- ^ expected an `FnMut<(i32,)>` closure, found `impl FnMut()`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: expected a closure taking 0 arguments, but one taking 1 argument was given
|
||||
note: required by a bound in `take`
|
||||
--> $DIR/mismatch-fn-trait.rs:1:18
|
||||
|
|
||||
LL | fn take(_f: impl FnMut(i32)) {}
|
||||
| ^^^^^^^^^^ required by this bound in `take`
|
||||
|
||||
error[E0277]: expected a `FnMut<(i32,)>` closure, found `impl FnOnce(i32)`
|
||||
--> $DIR/mismatch-fn-trait.rs:19:10
|
||||
|
|
||||
LL | take(f)
|
||||
| ---- ^ expected an `FnMut<(i32,)>` closure, found `impl FnOnce(i32)`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: `impl FnOnce(i32)` implements `FnOnce`, but it must implement `FnMut`, which is more general
|
||||
note: required by a bound in `take`
|
||||
--> $DIR/mismatch-fn-trait.rs:1:18
|
||||
|
|
||||
LL | fn take(_f: impl FnMut(i32)) {}
|
||||
| ^^^^^^^^^^ required by this bound in `take`
|
||||
|
||||
error[E0277]: expected a `FnMut<(i32,)>` closure, found `impl FnOnce(u32)`
|
||||
--> $DIR/mismatch-fn-trait.rs:24:10
|
||||
|
|
||||
LL | take(f)
|
||||
| ---- ^ expected an `FnMut<(i32,)>` closure, found `impl FnOnce(u32)`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: `impl FnOnce(u32)` implements `FnOnce`, but it must implement `FnMut`, which is more general
|
||||
= note: expected a closure with arguments `(u32,)`
|
||||
found a closure with arguments `(i32,)`
|
||||
note: required by a bound in `take`
|
||||
--> $DIR/mismatch-fn-trait.rs:1:18
|
||||
|
|
||||
LL | fn take(_f: impl FnMut(i32)) {}
|
||||
| ^^^^^^^^^^ required by this bound in `take`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -7,6 +7,7 @@ LL | let x = call_it(&S, 22);
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `Fn<(isize,)>` is not implemented for `S`
|
||||
= note: `S` implements `FnMut`, but it must implement `Fn`, which is more general
|
||||
note: required by a bound in `call_it`
|
||||
--> $DIR/unboxed-closures-fnmut-as-fn.rs:22:14
|
||||
|
|
||||
|
Loading…
Reference in New Issue
Block a user