1
Fork 0

Auto merge of #124277 - matthiaskrgr:rollup-zdb93i4, r=matthiaskrgr

Rollup of 7 pull requests

Successful merges:

 - #123680 (Deny gen keyword in `edition_2024_compat` lints)
 - #124057 (Fix ICE when ADT tail has type error)
 - #124168 (Use `DefiningOpaqueTypes::Yes` in rustdoc, where the `InferCtxt` is guaranteed to have no opaque types it can define)
 - #124197 (Move duplicated code in functions in `tests/rustdoc-gui/notable-trait.goml`)
 - #124200 (Improve handling of expr->field errors)
 - #124220 (Miri: detect wrong vtables in wide pointers)
 - #124266 (remove an unused type from the reentrant lock tests)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-04-23 06:23:20 +00:00
commit c67277301c
51 changed files with 672 additions and 252 deletions

View file

@ -82,12 +82,6 @@ const_eval_double_storage_live =
const_eval_dyn_call_not_a_method =
`dyn` call trying to call something that is not a method
const_eval_dyn_call_vtable_mismatch =
`dyn` call on a pointer whose vtable does not match its type
const_eval_dyn_star_call_vtable_mismatch =
`dyn*` call on a pointer whose vtable does not match its type
const_eval_error = {$error_kind ->
[static] could not evaluate static initializer
[const] evaluation of constant value failed
@ -192,6 +186,8 @@ const_eval_invalid_uninit_bytes_unknown =
const_eval_invalid_vtable_pointer =
using {$pointer} as vtable pointer but it does not point to a vtable
const_eval_invalid_vtable_trait =
using vtable for trait `{$vtable_trait}` but trait `{$expected_trait}` was expected
const_eval_live_drop =
destructor of `{$dropped_ty}` cannot be evaluated at compile-time
@ -401,9 +397,6 @@ const_eval_unterminated_c_string =
const_eval_unwind_past_top =
unwinding past the topmost frame of the stack
const_eval_upcast_mismatch =
upcast on a pointer whose vtable does not match its type
## The `front_matter`s here refer to either `const_eval_front_matter_invalid_value` or `const_eval_front_matter_invalid_value_with_path`.
## (We'd love to sort this differently to make that more clear but tidy won't let us...)
const_eval_validation_box_to_static = {$front_matter}: encountered a box pointing to a static variable in a constant
@ -450,6 +443,7 @@ const_eval_validation_invalid_fn_ptr = {$front_matter}: encountered {$value}, bu
const_eval_validation_invalid_ref_meta = {$front_matter}: encountered invalid reference metadata: total size is bigger than largest supported object
const_eval_validation_invalid_ref_slice_meta = {$front_matter}: encountered invalid reference metadata: slice is bigger than largest supported object
const_eval_validation_invalid_vtable_ptr = {$front_matter}: encountered {$value}, but expected a vtable pointer
const_eval_validation_invalid_vtable_trait = {$front_matter}: wrong trait in wide pointer vtable: expected `{$ref_trait}`, but encountered `{$vtable_trait}`
const_eval_validation_mutable_ref_to_immutable = {$front_matter}: encountered mutable reference or box pointing to read-only memory
const_eval_validation_never_val = {$front_matter}: encountered a value of the never type `!`
const_eval_validation_null_box = {$front_matter}: encountered a null box

View file

@ -498,6 +498,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
InvalidTag(_) => const_eval_invalid_tag,
InvalidFunctionPointer(_) => const_eval_invalid_function_pointer,
InvalidVTablePointer(_) => const_eval_invalid_vtable_pointer,
InvalidVTableTrait { .. } => const_eval_invalid_vtable_trait,
InvalidStr(_) => const_eval_invalid_str,
InvalidUninitBytes(None) => const_eval_invalid_uninit_bytes_unknown,
InvalidUninitBytes(Some(_)) => const_eval_invalid_uninit_bytes,
@ -537,6 +538,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
| DeadLocal
| UninhabitedEnumVariantWritten(_)
| UninhabitedEnumVariantRead(_) => {}
BoundsCheckFailed { len, index } => {
diag.arg("len", len);
diag.arg("index", index);
@ -544,6 +546,13 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
UnterminatedCString(ptr) | InvalidFunctionPointer(ptr) | InvalidVTablePointer(ptr) => {
diag.arg("pointer", ptr);
}
InvalidVTableTrait { expected_trait, vtable_trait } => {
diag.arg("expected_trait", expected_trait.to_string());
diag.arg(
"vtable_trait",
vtable_trait.map(|t| t.to_string()).unwrap_or_else(|| format!("<trivial>")),
);
}
PointerUseAfterFree(alloc_id, msg) => {
diag.arg("alloc_id", alloc_id)
.arg("bad_pointer_message", bad_pointer_message(msg, dcx));
@ -634,6 +643,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
UninhabitedEnumVariant => const_eval_validation_uninhabited_enum_variant,
Uninit { .. } => const_eval_validation_uninit,
InvalidVTablePtr { .. } => const_eval_validation_invalid_vtable_ptr,
InvalidMetaWrongTrait { .. } => const_eval_validation_invalid_vtable_trait,
InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Box } => {
const_eval_validation_invalid_box_slice_meta
}
@ -773,6 +783,13 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
DanglingPtrNoProvenance { pointer, .. } => {
err.arg("pointer", pointer);
}
InvalidMetaWrongTrait { expected_trait: ref_trait, vtable_trait } => {
err.arg("ref_trait", ref_trait.to_string());
err.arg(
"vtable_trait",
vtable_trait.map(|t| t.to_string()).unwrap_or_else(|| format!("<trivial>")),
);
}
NullPtr { .. }
| PtrToStatic { .. }
| ConstRefToMutable

View file

@ -393,6 +393,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let val = self.read_immediate(src)?;
if data_a.principal() == data_b.principal() {
// A NOP cast that doesn't actually change anything, should be allowed even with mismatching vtables.
// (But currently mismatching vtables violate the validity invariant so UB is triggered anyway.)
return self.write_immediate(*val, dest);
}
let (old_data, old_vptr) = val.to_scalar_pair();
@ -400,7 +401,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let old_vptr = old_vptr.to_pointer(self)?;
let (ty, old_trait) = self.get_ptr_vtable(old_vptr)?;
if old_trait != data_a.principal() {
throw_ub_custom!(fluent::const_eval_upcast_mismatch);
throw_ub!(InvalidVTableTrait {
expected_trait: data_a,
vtable_trait: old_trait,
});
}
let new_vptr = self.get_vtable_ptr(ty, data_b.principal())?;
self.write_immediate(Immediate::new_dyn_trait(old_data, new_vptr, self), dest)

View file

@ -1020,16 +1020,20 @@ where
pub(super) fn unpack_dyn_trait(
&self,
mplace: &MPlaceTy<'tcx, M::Provenance>,
expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
) -> InterpResult<'tcx, (MPlaceTy<'tcx, M::Provenance>, Pointer<Option<M::Provenance>>)> {
assert!(
matches!(mplace.layout.ty.kind(), ty::Dynamic(_, _, ty::Dyn)),
"`unpack_dyn_trait` only makes sense on `dyn*` types"
);
let vtable = mplace.meta().unwrap_meta().to_pointer(self)?;
let (ty, _) = self.get_ptr_vtable(vtable)?;
let layout = self.layout_of(ty)?;
let (ty, vtable_trait) = self.get_ptr_vtable(vtable)?;
if expected_trait.principal() != vtable_trait {
throw_ub!(InvalidVTableTrait { expected_trait, vtable_trait });
}
// This is a kind of transmute, from a place with unsized type and metadata to
// a place with sized type and no metadata.
let layout = self.layout_of(ty)?;
let mplace =
MPlaceTy { mplace: MemPlace { meta: MemPlaceMeta::None, ..mplace.mplace }, layout };
Ok((mplace, vtable))
@ -1040,6 +1044,7 @@ where
pub(super) fn unpack_dyn_star<P: Projectable<'tcx, M::Provenance>>(
&self,
val: &P,
expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
) -> InterpResult<'tcx, (P, Pointer<Option<M::Provenance>>)> {
assert!(
matches!(val.layout().ty.kind(), ty::Dynamic(_, _, ty::DynStar)),
@ -1048,10 +1053,12 @@ where
let data = self.project_field(val, 0)?;
let vtable = self.project_field(val, 1)?;
let vtable = self.read_pointer(&vtable.to_op(self)?)?;
let (ty, _) = self.get_ptr_vtable(vtable)?;
let (ty, vtable_trait) = self.get_ptr_vtable(vtable)?;
if expected_trait.principal() != vtable_trait {
throw_ub!(InvalidVTableTrait { expected_trait, vtable_trait });
}
// `data` is already the right thing but has the wrong type. So we transmute it.
let layout = self.layout_of(ty)?;
// `data` is already the right thing but has the wrong type. So we transmute it, by
// projecting with offset 0.
let data = data.transmute(layout, self)?;
Ok((data, vtable))
}

View file

@ -803,11 +803,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let (vptr, dyn_ty, adjusted_receiver) = if let ty::Dynamic(data, _, ty::DynStar) =
receiver_place.layout.ty.kind()
{
let (recv, vptr) = self.unpack_dyn_star(&receiver_place)?;
let (dyn_ty, dyn_trait) = self.get_ptr_vtable(vptr)?;
if dyn_trait != data.principal() {
throw_ub_custom!(fluent::const_eval_dyn_star_call_vtable_mismatch);
}
let (recv, vptr) = self.unpack_dyn_star(&receiver_place, data)?;
let (dyn_ty, _dyn_trait) = self.get_ptr_vtable(vptr)?;
(vptr, dyn_ty, recv.ptr())
} else {
@ -829,7 +826,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?;
let (dyn_ty, dyn_trait) = self.get_ptr_vtable(vptr)?;
if dyn_trait != data.principal() {
throw_ub_custom!(fluent::const_eval_dyn_call_vtable_mismatch);
throw_ub!(InvalidVTableTrait {
expected_trait: data,
vtable_trait: dyn_trait,
});
}
// It might be surprising that we use a pointer as the receiver even if this
@ -939,13 +939,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let place = self.force_allocation(place)?;
let place = match place.layout.ty.kind() {
ty::Dynamic(_, _, ty::Dyn) => {
ty::Dynamic(data, _, ty::Dyn) => {
// Dropping a trait object. Need to find actual drop fn.
self.unpack_dyn_trait(&place)?.0
self.unpack_dyn_trait(&place, data)?.0
}
ty::Dynamic(_, _, ty::DynStar) => {
ty::Dynamic(data, _, ty::DynStar) => {
// Dropping a `dyn*`. Need to find actual drop fn.
self.unpack_dyn_star(&place)?.0
self.unpack_dyn_star(&place, data)?.0
}
_ => {
debug_assert_eq!(

View file

@ -339,16 +339,22 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
) -> InterpResult<'tcx> {
let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(pointee.ty, self.ecx.param_env);
match tail.kind() {
ty::Dynamic(_, _, ty::Dyn) => {
ty::Dynamic(data, _, ty::Dyn) => {
let vtable = meta.unwrap_meta().to_pointer(self.ecx)?;
// Make sure it is a genuine vtable pointer.
let (_ty, _trait) = try_validation!(
let (_dyn_ty, dyn_trait) = try_validation!(
self.ecx.get_ptr_vtable(vtable),
self.path,
Ub(DanglingIntPointer(..) | InvalidVTablePointer(..)) =>
InvalidVTablePtr { value: format!("{vtable}") }
);
// FIXME: check if the type/trait match what ty::Dynamic says?
// Make sure it is for the right trait.
if dyn_trait != data.principal() {
throw_validation_failure!(
self.path,
InvalidMetaWrongTrait { expected_trait: data, vtable_trait: dyn_trait }
);
}
}
ty::Slice(..) | ty::Str => {
let _len = meta.unwrap_meta().to_target_usize(self.ecx)?;
@ -933,7 +939,16 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
}
}
_ => {
self.walk_value(op)?; // default handler
// default handler
try_validation!(
self.walk_value(op),
self.path,
// It's not great to catch errors here, since we can't give a very good path,
// but it's better than ICEing.
Ub(InvalidVTableTrait { expected_trait, vtable_trait }) => {
InvalidMetaWrongTrait { expected_trait, vtable_trait: *vtable_trait }
},
);
}
}

View file

@ -88,22 +88,22 @@ pub trait ValueVisitor<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>: Sized {
// Special treatment for special types, where the (static) layout is not sufficient.
match *ty.kind() {
// If it is a trait object, switch to the real type that was used to create it.
ty::Dynamic(_, _, ty::Dyn) => {
ty::Dynamic(data, _, ty::Dyn) => {
// Dyn types. This is unsized, and the actual dynamic type of the data is given by the
// vtable stored in the place metadata.
// unsized values are never immediate, so we can assert_mem_place
let op = v.to_op(self.ecx())?;
let dest = op.assert_mem_place();
let inner_mplace = self.ecx().unpack_dyn_trait(&dest)?.0;
let inner_mplace = self.ecx().unpack_dyn_trait(&dest, data)?.0;
trace!("walk_value: dyn object layout: {:#?}", inner_mplace.layout);
// recurse with the inner type
return self.visit_field(v, 0, &inner_mplace.into());
}
ty::Dynamic(_, _, ty::DynStar) => {
ty::Dynamic(data, _, ty::DynStar) => {
// DynStar types. Very different from a dyn type (but strangely part of the
// same variant in `TyKind`): These are pairs where the 2nd component is the
// vtable, and the first component is the data (which must be ptr-sized).
let data = self.ecx().unpack_dyn_star(v)?.0;
let data = self.ecx().unpack_dyn_star(v, data)?.0;
return self.visit_field(v, 0, &data);
}
// Slices do not need special handling here: they have `Array` field

View file

@ -1769,13 +1769,13 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
}
declare_lint! {
/// The `keyword_idents` lint detects edition keywords being used as an
/// The `keyword_idents_2018` lint detects edition keywords being used as an
/// identifier.
///
/// ### Example
///
/// ```rust,edition2015,compile_fail
/// #![deny(keyword_idents)]
/// #![deny(keyword_idents_2018)]
/// // edition 2015
/// fn dyn() {}
/// ```
@ -1804,7 +1804,7 @@ declare_lint! {
/// [editions]: https://doc.rust-lang.org/edition-guide/
/// [raw identifier]: https://doc.rust-lang.org/reference/identifiers.html
/// [`cargo fix`]: https://doc.rust-lang.org/cargo/commands/cargo-fix.html
pub KEYWORD_IDENTS,
pub KEYWORD_IDENTS_2018,
Allow,
"detects edition keywords being used as an identifier",
@future_incompatible = FutureIncompatibleInfo {
@ -1813,9 +1813,54 @@ declare_lint! {
};
}
declare_lint! {
/// The `keyword_idents_2024` lint detects edition keywords being used as an
/// identifier.
///
/// ### Example
///
/// ```rust,edition2015,compile_fail
/// #![deny(keyword_idents_2024)]
/// // edition 2015
/// fn gen() {}
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Rust [editions] allow the language to evolve without breaking
/// backwards compatibility. This lint catches code that uses new keywords
/// that are added to the language that are used as identifiers (such as a
/// variable name, function name, etc.). If you switch the compiler to a
/// new edition without updating the code, then it will fail to compile if
/// you are using a new keyword as an identifier.
///
/// You can manually change the identifiers to a non-keyword, or use a
/// [raw identifier], for example `r#gen`, to transition to a new edition.
///
/// This lint solves the problem automatically. It is "allow" by default
/// because the code is perfectly valid in older editions. The [`cargo
/// fix`] tool with the `--edition` flag will switch this lint to "warn"
/// and automatically apply the suggested fix from the compiler (which is
/// to use a raw identifier). This provides a completely automated way to
/// update old code for a new edition.
///
/// [editions]: https://doc.rust-lang.org/edition-guide/
/// [raw identifier]: https://doc.rust-lang.org/reference/identifiers.html
/// [`cargo fix`]: https://doc.rust-lang.org/cargo/commands/cargo-fix.html
pub KEYWORD_IDENTS_2024,
Allow,
"detects edition keywords being used as an identifier",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::EditionError(Edition::Edition2024),
reference: "issue #49716 <https://github.com/rust-lang/rust/issues/49716>",
};
}
declare_lint_pass!(
/// Check for uses of edition keywords used as an identifier.
KeywordIdents => [KEYWORD_IDENTS]
KeywordIdents => [KEYWORD_IDENTS_2018, KEYWORD_IDENTS_2024]
);
struct UnderMacro(bool);
@ -1841,42 +1886,39 @@ impl KeywordIdents {
UnderMacro(under_macro): UnderMacro,
ident: Ident,
) {
let next_edition = match cx.sess().edition() {
Edition::Edition2015 => {
match ident.name {
kw::Async | kw::Await | kw::Try => Edition::Edition2018,
let (lint, edition) = match ident.name {
kw::Async | kw::Await | kw::Try => (KEYWORD_IDENTS_2018, Edition::Edition2018),
// rust-lang/rust#56327: Conservatively do not
// attempt to report occurrences of `dyn` within
// macro definitions or invocations, because `dyn`
// can legitimately occur as a contextual keyword
// in 2015 code denoting its 2018 meaning, and we
// do not want rustfix to inject bugs into working
// code by rewriting such occurrences.
//
// But if we see `dyn` outside of a macro, we know
// its precise role in the parsed AST and thus are
// assured this is truly an attempt to use it as
// an identifier.
kw::Dyn if !under_macro => Edition::Edition2018,
// rust-lang/rust#56327: Conservatively do not
// attempt to report occurrences of `dyn` within
// macro definitions or invocations, because `dyn`
// can legitimately occur as a contextual keyword
// in 2015 code denoting its 2018 meaning, and we
// do not want rustfix to inject bugs into working
// code by rewriting such occurrences.
//
// But if we see `dyn` outside of a macro, we know
// its precise role in the parsed AST and thus are
// assured this is truly an attempt to use it as
// an identifier.
kw::Dyn if !under_macro => (KEYWORD_IDENTS_2018, Edition::Edition2018),
_ => return,
}
}
kw::Gen => (KEYWORD_IDENTS_2024, Edition::Edition2024),
// There are no new keywords yet for the 2018 edition and beyond.
_ => return,
};
// Don't lint `r#foo`.
if cx.sess().psess.raw_identifier_spans.contains(ident.span) {
if ident.span.edition() >= edition
|| cx.sess().psess.raw_identifier_spans.contains(ident.span)
{
return;
}
cx.emit_span_lint(
KEYWORD_IDENTS,
lint,
ident.span,
BuiltinKeywordIdents { kw: ident, next: next_edition, suggestion: ident.span },
BuiltinKeywordIdents { kw: ident, next: edition, suggestion: ident.span },
);
}
}

View file

@ -312,6 +312,8 @@ fn register_builtins(store: &mut LintStore) {
// MACRO_USE_EXTERN_CRATE
);
add_lint_group!("keyword_idents", KEYWORD_IDENTS_2018, KEYWORD_IDENTS_2024);
add_lint_group!(
"refining_impl_trait",
REFINING_IMPL_TRAIT_REACHABLE,
@ -324,7 +326,7 @@ fn register_builtins(store: &mut LintStore) {
store.register_renamed("bare_trait_object", "bare_trait_objects");
store.register_renamed("unstable_name_collision", "unstable_name_collisions");
store.register_renamed("unused_doc_comment", "unused_doc_comments");
store.register_renamed("async_idents", "keyword_idents");
store.register_renamed("async_idents", "keyword_idents_2018");
store.register_renamed("exceeding_bitshifts", "arithmetic_overflow");
store.register_renamed("redundant_semicolon", "redundant_semicolons");
store.register_renamed("overlapping_patterns", "overlapping_range_endpoints");

View file

@ -2,7 +2,7 @@ use super::{AllocId, AllocRange, ConstAllocation, Pointer, Scalar};
use crate::error;
use crate::mir::{ConstAlloc, ConstValue};
use crate::ty::{layout, tls, Ty, TyCtxt, ValTree};
use crate::ty::{self, layout, tls, Ty, TyCtxt, ValTree};
use rustc_ast_ir::Mutability;
use rustc_data_structures::sync::Lock;
@ -344,6 +344,11 @@ pub enum UndefinedBehaviorInfo<'tcx> {
InvalidFunctionPointer(Pointer<AllocId>),
/// Using a pointer-not-to-a-vtable as vtable pointer.
InvalidVTablePointer(Pointer<AllocId>),
/// Using a vtable for the wrong trait.
InvalidVTableTrait {
expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
vtable_trait: Option<ty::PolyExistentialTraitRef<'tcx>>,
},
/// Using a string that is not valid UTF-8,
InvalidStr(std::str::Utf8Error),
/// Using uninitialized data where it is not allowed.
@ -414,34 +419,86 @@ impl From<PointerKind> for ExpectedKind {
#[derive(Debug)]
pub enum ValidationErrorKind<'tcx> {
PointerAsInt { expected: ExpectedKind },
PointerAsInt {
expected: ExpectedKind,
},
PartialPointer,
PtrToUninhabited { ptr_kind: PointerKind, ty: Ty<'tcx> },
PtrToStatic { ptr_kind: PointerKind },
PtrToUninhabited {
ptr_kind: PointerKind,
ty: Ty<'tcx>,
},
PtrToStatic {
ptr_kind: PointerKind,
},
ConstRefToMutable,
ConstRefToExtern,
MutableRefToImmutable,
UnsafeCellInImmutable,
NullFnPtr,
NeverVal,
NullablePtrOutOfRange { range: WrappingRange, max_value: u128 },
PtrOutOfRange { range: WrappingRange, max_value: u128 },
OutOfRange { value: String, range: WrappingRange, max_value: u128 },
UninhabitedVal { ty: Ty<'tcx> },
InvalidEnumTag { value: String },
NullablePtrOutOfRange {
range: WrappingRange,
max_value: u128,
},
PtrOutOfRange {
range: WrappingRange,
max_value: u128,
},
OutOfRange {
value: String,
range: WrappingRange,
max_value: u128,
},
UninhabitedVal {
ty: Ty<'tcx>,
},
InvalidEnumTag {
value: String,
},
UninhabitedEnumVariant,
Uninit { expected: ExpectedKind },
InvalidVTablePtr { value: String },
InvalidMetaSliceTooLarge { ptr_kind: PointerKind },
InvalidMetaTooLarge { ptr_kind: PointerKind },
UnalignedPtr { ptr_kind: PointerKind, required_bytes: u64, found_bytes: u64 },
NullPtr { ptr_kind: PointerKind },
DanglingPtrNoProvenance { ptr_kind: PointerKind, pointer: String },
DanglingPtrOutOfBounds { ptr_kind: PointerKind },
DanglingPtrUseAfterFree { ptr_kind: PointerKind },
InvalidBool { value: String },
InvalidChar { value: String },
InvalidFnPtr { value: String },
Uninit {
expected: ExpectedKind,
},
InvalidVTablePtr {
value: String,
},
InvalidMetaWrongTrait {
expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
vtable_trait: Option<ty::PolyExistentialTraitRef<'tcx>>,
},
InvalidMetaSliceTooLarge {
ptr_kind: PointerKind,
},
InvalidMetaTooLarge {
ptr_kind: PointerKind,
},
UnalignedPtr {
ptr_kind: PointerKind,
required_bytes: u64,
found_bytes: u64,
},
NullPtr {
ptr_kind: PointerKind,
},
DanglingPtrNoProvenance {
ptr_kind: PointerKind,
pointer: String,
},
DanglingPtrOutOfBounds {
ptr_kind: PointerKind,
},
DanglingPtrUseAfterFree {
ptr_kind: PointerKind,
},
InvalidBool {
value: String,
},
InvalidChar {
value: String,
},
InvalidFnPtr {
value: String,
},
}
/// Error information for when the program did something that might (or might not) be correct

View file

@ -338,6 +338,10 @@ impl<'tcx> SizeSkeleton<'tcx> {
debug_assert!(tail.has_non_region_param());
Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) })
}
ty::Error(guar) => {
// Fixes ICE #124031
return Err(tcx.arena.alloc(LayoutError::ReferencesError(*guar)));
}
_ => bug!(
"SizeSkeleton::compute({ty}): layout errored ({err:?}), yet \
tail `{tail}` is not a type parameter or a projection",

View file

@ -230,6 +230,10 @@ parse_expected_struct_field = expected one of `,`, `:`, or `{"}"}`, found `{$tok
parse_expected_trait_in_trait_impl_found_type = expected a trait, found type
parse_expr_rarrow_call = `->` used for field access or method call
.suggestion = try using `.` instead
.help = the `.` operator will dereference the value if needed
parse_extern_crate_name_with_dashes = crate name using dashes are not valid in `extern crate` statements
.label = dash-separated idents are not valid
.suggestion = if the original crate name uses dashes you need to use underscores in the code

View file

@ -2988,3 +2988,12 @@ pub(crate) struct AsyncImpl {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(parse_expr_rarrow_call)]
#[help]
pub(crate) struct ExprRArrowCall {
#[primary_span]
#[suggestion(style = "short", applicability = "machine-applicable", code = ".")]
pub span: Span,
}

View file

@ -979,6 +979,12 @@ impl<'a> Parser<'a> {
// we are using noexpect here because we don't expect a `.` directly after a `return`
// which could be suggested otherwise
self.eat_noexpect(&token::Dot)
} else if self.token.kind == TokenKind::RArrow && self.may_recover() {
// Recovery for `expr->suffix`.
self.bump();
let span = self.prev_token.span;
self.dcx().emit_err(errors::ExprRArrowCall { span });
true
} else {
self.eat(&token::Dot)
};

View file

@ -784,7 +784,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
match (evaluate(c1), evaluate(c2)) {
(Ok(c1), Ok(c2)) => {
match selcx.infcx.at(&obligation.cause, obligation.param_env).eq(DefineOpaqueTypes::No,c1, c2)
match selcx.infcx.at(&obligation.cause, obligation.param_env).eq(DefineOpaqueTypes::Yes,c1, c2)
{
Ok(_) => (),
Err(_) => return false,