Auto merge of #120903 - matthiaskrgr:rollup-tmsuzth, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #119213 (simd intrinsics: add simd_shuffle_generic and other missing intrinsics) - #120272 (Suppress suggestions in derive macro) - #120773 (large_assignments: Allow moves into functions) - #120874 (Take empty `where` bounds into account when suggesting predicates) - #120882 (interpret/write_discriminant: when encoding niched variant, ensure the stored value matches) - #120883 (interpret: rename ReadExternStatic → ExternStatic) - #120890 (Adapt `llvm-has-rust-patches` validation to take `llvm-config` into account.) - #120895 (don't skip coercions for types with errors) - #120896 (Print kind of coroutine closure) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
a166af7729
47 changed files with 491 additions and 137 deletions
|
@ -98,6 +98,8 @@ const_eval_error = {$error_kind ->
|
|||
const_eval_exact_div_has_remainder =
|
||||
exact_div: {$a} cannot be divided by {$b} without remainder
|
||||
|
||||
const_eval_extern_static =
|
||||
cannot access extern static ({$did})
|
||||
const_eval_fn_ptr_call =
|
||||
function pointers need an RFC before allowed to be called in {const_eval_const_context}s
|
||||
const_eval_for_loop_into_iter_non_const =
|
||||
|
@ -172,6 +174,10 @@ const_eval_invalid_meta =
|
|||
invalid metadata in wide pointer: total size is bigger than largest supported object
|
||||
const_eval_invalid_meta_slice =
|
||||
invalid metadata in wide pointer: slice is bigger than largest supported object
|
||||
|
||||
const_eval_invalid_niched_enum_variant_written =
|
||||
trying to set discriminant of a {$ty} to the niched variant, but the value does not match
|
||||
|
||||
const_eval_invalid_str =
|
||||
this string is not valid UTF-8: {$err}
|
||||
const_eval_invalid_tag =
|
||||
|
@ -298,8 +304,6 @@ const_eval_raw_ptr_to_int =
|
|||
.note = at compile-time, pointers do not have an integer value
|
||||
.note2 = avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
|
||||
|
||||
const_eval_read_extern_static =
|
||||
cannot read from extern static ({$did})
|
||||
const_eval_read_pointer_as_int =
|
||||
unable to turn pointer into integer
|
||||
const_eval_realloc_or_alloc_with_offset =
|
||||
|
|
|
@ -497,6 +497,9 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
|
|||
ScalarSizeMismatch(_) => const_eval_scalar_size_mismatch,
|
||||
UninhabitedEnumVariantWritten(_) => const_eval_uninhabited_enum_variant_written,
|
||||
UninhabitedEnumVariantRead(_) => const_eval_uninhabited_enum_variant_read,
|
||||
InvalidNichedEnumVariantWritten { .. } => {
|
||||
const_eval_invalid_niched_enum_variant_written
|
||||
}
|
||||
AbiMismatchArgument { .. } => const_eval_incompatible_types,
|
||||
AbiMismatchReturn { .. } => const_eval_incompatible_return_types,
|
||||
}
|
||||
|
@ -585,6 +588,9 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
|
|||
builder.arg("target_size", info.target_size);
|
||||
builder.arg("data_size", info.data_size);
|
||||
}
|
||||
InvalidNichedEnumVariantWritten { enum_ty } => {
|
||||
builder.arg("ty", enum_ty.to_string());
|
||||
}
|
||||
AbiMismatchArgument { caller_ty, callee_ty }
|
||||
| AbiMismatchReturn { caller_ty, callee_ty } => {
|
||||
builder.arg("caller_ty", caller_ty.to_string());
|
||||
|
@ -793,7 +799,7 @@ impl ReportErrorExt for UnsupportedOpInfo {
|
|||
UnsupportedOpInfo::ReadPartialPointer(_) => const_eval_partial_pointer_copy,
|
||||
UnsupportedOpInfo::ReadPointerAsInt(_) => const_eval_read_pointer_as_int,
|
||||
UnsupportedOpInfo::ThreadLocalStatic(_) => const_eval_thread_local_static,
|
||||
UnsupportedOpInfo::ReadExternStatic(_) => const_eval_read_extern_static,
|
||||
UnsupportedOpInfo::ExternStatic(_) => const_eval_extern_static,
|
||||
}
|
||||
}
|
||||
fn add_args<G: EmissionGuarantee>(self, _: &DiagCtxt, builder: &mut DiagnosticBuilder<'_, G>) {
|
||||
|
@ -812,7 +818,7 @@ impl ReportErrorExt for UnsupportedOpInfo {
|
|||
OverwritePartialPointer(ptr) | ReadPartialPointer(ptr) => {
|
||||
builder.arg("ptr", ptr);
|
||||
}
|
||||
ThreadLocalStatic(did) | ReadExternStatic(did) => {
|
||||
ThreadLocalStatic(did) | ExternStatic(did) => {
|
||||
builder.arg("did", format!("{did:?}"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,6 +85,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
// Write result.
|
||||
let niche_dest = self.project_field(dest, tag_field)?;
|
||||
self.write_immediate(*tag_val, &niche_dest)?;
|
||||
} else {
|
||||
// The untagged variant is implicitly encoded simply by having a value that is
|
||||
// outside the niche variants. But what if the data stored here does not
|
||||
// actually encode this variant? That would be bad! So let's double-check...
|
||||
let actual_variant = self.read_discriminant(&dest.to_op(self)?)?;
|
||||
if actual_variant != variant_index {
|
||||
throw_ub!(InvalidNichedEnumVariantWritten { enum_ty: dest.layout().ty });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -557,7 +557,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
if self.tcx.is_foreign_item(def_id) {
|
||||
// This is unreachable in Miri, but can happen in CTFE where we actually *do* support
|
||||
// referencing arbitrary (declared) extern statics.
|
||||
throw_unsup!(ReadExternStatic(def_id));
|
||||
throw_unsup!(ExternStatic(def_id));
|
||||
}
|
||||
|
||||
// We don't give a span -- statics don't need that, they cannot be generic or associated.
|
||||
|
|
|
@ -516,6 +516,17 @@ impl Diagnostic {
|
|||
|
||||
/// Helper for pushing to `self.suggestions`, if available (not disable).
|
||||
fn push_suggestion(&mut self, suggestion: CodeSuggestion) {
|
||||
for subst in &suggestion.substitutions {
|
||||
for part in &subst.parts {
|
||||
let span = part.span;
|
||||
let call_site = span.ctxt().outer_expn_data().call_site;
|
||||
if span.in_derive_expansion() && span.overlaps_or_adjacent(call_site) {
|
||||
// Ignore if spans is from derive macro.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(suggestions) = &mut self.suggestions {
|
||||
suggestions.push(suggestion);
|
||||
}
|
||||
|
|
|
@ -186,17 +186,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||
let b = self.shallow_resolve(b);
|
||||
debug!("Coerce.tys({:?} => {:?})", a, b);
|
||||
|
||||
// Just ignore error types.
|
||||
if let Err(guar) = (a, b).error_reported() {
|
||||
// Best-effort try to unify these types -- we're already on the error path,
|
||||
// so this will have the side-effect of making sure we have no ambiguities
|
||||
// due to `[type error]` and `_` not coercing together.
|
||||
let _ = self.commit_if_ok(|_| {
|
||||
self.at(&self.cause, self.param_env).eq(DefineOpaqueTypes::Yes, a, b)
|
||||
});
|
||||
return success(vec![], Ty::new_error(self.fcx.tcx, guar), vec![]);
|
||||
}
|
||||
|
||||
// Coercing from `!` to any type is allowed:
|
||||
if a.is_never() {
|
||||
return success(simple(Adjust::NeverToAny)(b), b, vec![]);
|
||||
|
|
|
@ -356,6 +356,8 @@ pub enum UndefinedBehaviorInfo<'tcx> {
|
|||
UninhabitedEnumVariantWritten(VariantIdx),
|
||||
/// An uninhabited enum variant is projected.
|
||||
UninhabitedEnumVariantRead(VariantIdx),
|
||||
/// Trying to set discriminant to the niched variant, but the value does not match.
|
||||
InvalidNichedEnumVariantWritten { enum_ty: Ty<'tcx> },
|
||||
/// ABI-incompatible argument types.
|
||||
AbiMismatchArgument { caller_ty: Ty<'tcx>, callee_ty: Ty<'tcx> },
|
||||
/// ABI-incompatible return types.
|
||||
|
@ -468,7 +470,7 @@ pub enum UnsupportedOpInfo {
|
|||
/// Accessing thread local statics
|
||||
ThreadLocalStatic(DefId),
|
||||
/// Accessing an unsupported extern static.
|
||||
ReadExternStatic(DefId),
|
||||
ExternStatic(DefId),
|
||||
}
|
||||
|
||||
/// Error information for when the program exhausted the resources granted to it
|
||||
|
|
|
@ -358,11 +358,17 @@ pub fn suggest_constraining_type_params<'a>(
|
|||
// trait Foo<T=()> {... }
|
||||
// - insert: `where T: Zar`
|
||||
if matches!(param.kind, hir::GenericParamKind::Type { default: Some(_), .. }) {
|
||||
// If we are here and the where clause span is of non-zero length
|
||||
// it means we're dealing with an empty where clause like this:
|
||||
// fn foo<X>(x: X) where { ... }
|
||||
// In that case we don't want to add another "where" (Fixes #120838)
|
||||
let where_prefix = if generics.where_clause_span.is_empty() { " where" } else { "" };
|
||||
|
||||
// Suggest a bound, but there is no existing `where` clause *and* the type param has a
|
||||
// default (`<T=Foo>`), so we suggest adding `where T: Bar`.
|
||||
suggestions.push((
|
||||
generics.tail_span_for_predicate_suggestion(),
|
||||
format!(" where {param_name}: {constraint}"),
|
||||
format!("{where_prefix} {param_name}: {constraint}"),
|
||||
SuggestChangingConstraintsMessage::RestrictTypeFurther { ty: param_name },
|
||||
));
|
||||
continue;
|
||||
|
|
|
@ -877,7 +877,24 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
ty::CoroutineClosure(did, args) => {
|
||||
p!(write("{{"));
|
||||
if !self.should_print_verbose() {
|
||||
p!(write("coroutine-closure"));
|
||||
match self.tcx().coroutine_kind(self.tcx().coroutine_for_closure(did)).unwrap()
|
||||
{
|
||||
hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Async,
|
||||
hir::CoroutineSource::Closure,
|
||||
) => p!("async closure"),
|
||||
hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::AsyncGen,
|
||||
hir::CoroutineSource::Closure,
|
||||
) => p!("async gen closure"),
|
||||
hir::CoroutineKind::Desugared(
|
||||
hir::CoroutineDesugaring::Gen,
|
||||
hir::CoroutineSource::Closure,
|
||||
) => p!("gen closure"),
|
||||
_ => unreachable!(
|
||||
"coroutine from coroutine-closure should have CoroutineSource::Closure"
|
||||
),
|
||||
}
|
||||
// FIXME(eddyb) should use `def_span`.
|
||||
if let Some(did) = did.as_local() {
|
||||
if self.tcx().sess.opts.unstable_opts.span_free_formats {
|
||||
|
|
|
@ -666,7 +666,15 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> {
|
|||
debug!(?def_id, ?fn_span);
|
||||
|
||||
for arg in args {
|
||||
if let Some(too_large_size) = self.operand_size_if_too_large(limit, &arg.node) {
|
||||
// Moving args into functions is typically implemented with pointer
|
||||
// passing at the llvm-ir level and not by memcpy's. So always allow
|
||||
// moving args into functions.
|
||||
let operand: &mir::Operand<'tcx> = &arg.node;
|
||||
if let mir::Operand::Move(_) = operand {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(too_large_size) = self.operand_size_if_too_large(limit, operand) {
|
||||
self.lint_large_assignment(limit.0, too_large_size, location, arg.span);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -625,6 +625,13 @@ impl Span {
|
|||
span.lo < other.hi && other.lo < span.hi
|
||||
}
|
||||
|
||||
/// Returns `true` if `self` touches or adjoins `other`.
|
||||
pub fn overlaps_or_adjacent(self, other: Span) -> bool {
|
||||
let span = self.data();
|
||||
let other = other.data();
|
||||
span.lo <= other.hi && other.lo <= span.hi
|
||||
}
|
||||
|
||||
/// Returns `true` if the spans are equal with regards to the source text.
|
||||
///
|
||||
/// Use this instead of `==` when either span could be generated code,
|
||||
|
|
|
@ -190,14 +190,27 @@ extern "platform-intrinsic" {
|
|||
///
|
||||
/// `T` must be a vector.
|
||||
///
|
||||
/// `U` must be a const array of `i32`s.
|
||||
/// `U` must be a **const** array of `i32`s. This means it must either refer to a named
|
||||
/// const or be given as an inline const expression (`const { ... }`).
|
||||
///
|
||||
/// `V` must be a vector with the same element type as `T` and the same length as `U`.
|
||||
///
|
||||
/// Concatenates `x` and `y`, then returns a new vector such that each element is selected from
|
||||
/// the concatenation by the matching index in `idx`.
|
||||
/// Returns a new vector such that element `i` is selected from `xy[idx[i]]`, where `xy`
|
||||
/// is the concatenation of `x` and `y`. It is a compile-time error if `idx[i]` is out-of-bounds
|
||||
/// of `xy`.
|
||||
pub fn simd_shuffle<T, U, V>(x: T, y: T, idx: U) -> V;
|
||||
|
||||
/// Shuffle two vectors by const indices.
|
||||
///
|
||||
/// `T` must be a vector.
|
||||
///
|
||||
/// `U` must be a vector with the same element type as `T` and the same length as `IDX`.
|
||||
///
|
||||
/// Returns a new vector such that element `i` is selected from `xy[IDX[i]]`, where `xy`
|
||||
/// is the concatenation of `x` and `y`. It is a compile-time error if `IDX[i]` is out-of-bounds
|
||||
/// of `xy`.
|
||||
pub fn simd_shuffle_generic<T, U, const IDX: &'static [u32]>(x: T, y: T) -> U;
|
||||
|
||||
/// Read a vector of pointers.
|
||||
///
|
||||
/// `T` must be a vector.
|
||||
|
@ -232,6 +245,9 @@ extern "platform-intrinsic" {
|
|||
/// corresponding value in `val` to the pointer.
|
||||
/// Otherwise if the corresponding value in `mask` is `0`, do nothing.
|
||||
///
|
||||
/// The stores happen in left-to-right order.
|
||||
/// (This is relevant in case two of the stores overlap.)
|
||||
///
|
||||
/// # Safety
|
||||
/// Unmasked values in `T` must be writeable as if by `<ptr>::write` (e.g. aligned to the element
|
||||
/// type).
|
||||
|
@ -468,4 +484,36 @@ extern "platform-intrinsic" {
|
|||
///
|
||||
/// `T` must be a vector of integers.
|
||||
pub fn simd_cttz<T>(x: T) -> T;
|
||||
|
||||
/// Round up each element to the next highest integer-valued float.
|
||||
///
|
||||
/// `T` must be a vector of floats.
|
||||
pub fn simd_ceil<T>(x: T) -> T;
|
||||
|
||||
/// Round down each element to the next lowest integer-valued float.
|
||||
///
|
||||
/// `T` must be a vector of floats.
|
||||
pub fn simd_floor<T>(x: T) -> T;
|
||||
|
||||
/// Round each element to the closest integer-valued float.
|
||||
/// Ties are resolved by rounding away from 0.
|
||||
///
|
||||
/// `T` must be a vector of floats.
|
||||
pub fn simd_round<T>(x: T) -> T;
|
||||
|
||||
/// Return the integer part of each element as an integer-valued float.
|
||||
/// In other words, non-integer values are truncated towards zero.
|
||||
///
|
||||
/// `T` must be a vector of floats.
|
||||
pub fn simd_trunc<T>(x: T) -> T;
|
||||
|
||||
/// Takes the square root of each element.
|
||||
///
|
||||
/// `T` must be a vector of floats.
|
||||
pub fn simd_fsqrt<T>(x: T) -> T;
|
||||
|
||||
/// Computes `(x*y) + z` for each element, but without any intermediate rounding.
|
||||
///
|
||||
/// `T` must be a vector of floats.
|
||||
pub fn simd_fma<T>(x: T, y: T, z: T) -> T;
|
||||
}
|
||||
|
|
|
@ -1810,10 +1810,9 @@ impl Config {
|
|||
target.llvm_config = Some(config.src.join(s));
|
||||
}
|
||||
if let Some(patches) = cfg.llvm_has_rust_patches {
|
||||
assert_eq!(
|
||||
config.submodules,
|
||||
Some(false),
|
||||
"cannot set `llvm-has-rust-patches` for a managed submodule (set `build.submodules = false` if you want to apply patches)"
|
||||
assert!(
|
||||
config.submodules == Some(false) || cfg.llvm_config.is_some(),
|
||||
"use of `llvm-has-rust-patches` is restricted to cases where either submodules are disabled or llvm-config been provided"
|
||||
);
|
||||
target.llvm_has_rust_patches = Some(patches);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
#![feature(core_intrinsics)]
|
||||
#![feature(custom_mir)]
|
||||
|
||||
use std::intrinsics::mir::*;
|
||||
use std::num::NonZeroI32;
|
||||
|
||||
// We define our own option type so that we can control the varian indices.
|
||||
#[allow(unused)]
|
||||
enum Option<T> {
|
||||
None,
|
||||
Some(T),
|
||||
}
|
||||
use Option::*;
|
||||
|
||||
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
||||
fn set_discriminant(ptr: &mut Option<NonZeroI32>) {
|
||||
mir! {
|
||||
{
|
||||
// We set the discriminant to `Some`, which is a NOP since this is the niched variant.
|
||||
// However, the enum is actually encoding `None` currently! That's not good...
|
||||
SetDiscriminant(*ptr, 1);
|
||||
//~^ ERROR: trying to set discriminant of a Option<std::num::NonZero<i32>> to the niched variant, but the value does not match
|
||||
Return()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let mut v = None;
|
||||
set_discriminant(&mut v);
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
error: Undefined Behavior: trying to set discriminant of a Option<std::num::NonZero<i32>> to the niched variant, but the value does not match
|
||||
--> $DIR/enum-set-discriminant-niche-variant-wrong.rs:LL:CC
|
||||
|
|
||||
LL | SetDiscriminant(*ptr, 1);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ trying to set discriminant of a Option<std::num::NonZero<i32>> to the niched variant, but the value does not match
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
= note: BACKTRACE:
|
||||
= note: inside `set_discriminant` at $DIR/enum-set-discriminant-niche-variant-wrong.rs:LL:CC
|
||||
note: inside `main`
|
||||
--> $DIR/enum-set-discriminant-niche-variant-wrong.rs:LL:CC
|
||||
|
|
||||
LL | set_discriminant(&mut v);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_move
|
||||
|
||||
fn main::{closure#0}::{closure#0}(_1: {coroutine-closure@$DIR/async_closure_shims.rs:39:33: 39:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10} {
|
||||
fn main::{closure#0}::{closure#0}(_1: {async closure@$DIR/async_closure_shims.rs:39:33: 39:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10} {
|
||||
let mut _0: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10};
|
||||
|
||||
bb0: {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_move
|
||||
|
||||
fn main::{closure#0}::{closure#0}(_1: {coroutine-closure@$DIR/async_closure_shims.rs:39:33: 39:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10} {
|
||||
fn main::{closure#0}::{closure#0}(_1: {async closure@$DIR/async_closure_shims.rs:39:33: 39:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10} {
|
||||
let mut _0: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10};
|
||||
|
||||
bb0: {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_mut
|
||||
|
||||
fn main::{closure#0}::{closure#0}(_1: &mut {coroutine-closure@$DIR/async_closure_shims.rs:39:33: 39:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10} {
|
||||
fn main::{closure#0}::{closure#0}(_1: &mut {async closure@$DIR/async_closure_shims.rs:39:33: 39:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10} {
|
||||
debug a => _2;
|
||||
debug b => ((*_1).0: i32);
|
||||
let mut _0: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// MIR for `main::{closure#0}::{closure#0}` 0 coroutine_closure_by_mut
|
||||
|
||||
fn main::{closure#0}::{closure#0}(_1: &mut {coroutine-closure@$DIR/async_closure_shims.rs:39:33: 39:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10} {
|
||||
fn main::{closure#0}::{closure#0}(_1: &mut {async closure@$DIR/async_closure_shims.rs:39:33: 39:52}, _2: i32) -> {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10} {
|
||||
debug a => _2;
|
||||
debug b => ((*_1).0: i32);
|
||||
let mut _0: {async closure body@$DIR/async_closure_shims.rs:39:53: 42:10};
|
||||
|
|
|
@ -5,5 +5,5 @@
|
|||
fn main() {
|
||||
fn needs_fn(x: impl FnOnce()) {}
|
||||
needs_fn(async || {});
|
||||
//~^ ERROR expected `{coroutine-closure@is-not-fn.rs:7:14}` to be a closure that returns `()`
|
||||
//~^ ERROR expected `{async closure@is-not-fn.rs:7:14}` to be a closure that returns `()`
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
error[E0271]: expected `{coroutine-closure@is-not-fn.rs:7:14}` to be a closure that returns `()`, but it returns `{async closure body@$DIR/is-not-fn.rs:7:23: 7:25}`
|
||||
error[E0271]: expected `{async closure@is-not-fn.rs:7:14}` to be a closure that returns `()`, but it returns `{async closure body@$DIR/is-not-fn.rs:7:23: 7:25}`
|
||||
--> $DIR/is-not-fn.rs:7:14
|
||||
|
|
||||
LL | needs_fn(async || {});
|
||||
|
|
|
@ -2,7 +2,7 @@ error[E0382]: use of moved value: `x`
|
|||
--> $DIR/move-consuming-capture.rs:17:9
|
||||
|
|
||||
LL | let x = async move || {
|
||||
| - move occurs because `x` has type `{coroutine-closure@$DIR/move-consuming-capture.rs:13:17: 13:30}`, which does not implement the `Copy` trait
|
||||
| - move occurs because `x` has type `{async closure@$DIR/move-consuming-capture.rs:13:17: 13:30}`, which does not implement the `Copy` trait
|
||||
...
|
||||
LL | x().await;
|
||||
| --- `x` moved due to this method call
|
||||
|
|
15
tests/ui/coercion/type-errors.rs
Normal file
15
tests/ui/coercion/type-errors.rs
Normal file
|
@ -0,0 +1,15 @@
|
|||
// Regression test for an ICE: https://github.com/rust-lang/rust/issues/120884
|
||||
// We still need to properly go through coercions between types with errors instead of
|
||||
// shortcutting and returning success, because we need the adjustments for building the MIR.
|
||||
|
||||
pub fn has_error() -> TypeError {}
|
||||
//~^ ERROR cannot find type `TypeError` in this scope
|
||||
|
||||
pub fn cast() -> *const u8 {
|
||||
// Casting a function item to a data pointer in valid in HIR, but invalid in MIR.
|
||||
// We need an adjustment (ReifyFnPointer) to insert a cast from the function item
|
||||
// to a function pointer as a separate MIR statement.
|
||||
has_error as *const u8
|
||||
}
|
||||
|
||||
fn main() {}
|
9
tests/ui/coercion/type-errors.stderr
Normal file
9
tests/ui/coercion/type-errors.stderr
Normal file
|
@ -0,0 +1,9 @@
|
|||
error[E0412]: cannot find type `TypeError` in this scope
|
||||
--> $DIR/type-errors.rs:5:23
|
||||
|
|
||||
LL | pub fn has_error() -> TypeError {}
|
||||
| ^^^^^^^^^ not found in this scope
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0412`.
|
24
tests/ui/consts/miri_unleashed/extern-static.rs
Normal file
24
tests/ui/consts/miri_unleashed/extern-static.rs
Normal file
|
@ -0,0 +1,24 @@
|
|||
// compile-flags: -Zunleash-the-miri-inside-of-you
|
||||
#![feature(thread_local)]
|
||||
#![allow(static_mut_ref)]
|
||||
|
||||
extern "C" {
|
||||
static mut DATA: u8;
|
||||
}
|
||||
|
||||
// Make sure we catch accessing extern static.
|
||||
static TEST_READ: () = {
|
||||
unsafe { let _val = DATA; }
|
||||
//~^ ERROR could not evaluate static initializer
|
||||
//~| NOTE cannot access extern static
|
||||
};
|
||||
static TEST_WRITE: () = {
|
||||
unsafe { DATA = 0; }
|
||||
//~^ ERROR could not evaluate static initializer
|
||||
//~| NOTE cannot access extern static
|
||||
};
|
||||
|
||||
// Just creating a reference is fine, as long as we are not reading or writing.
|
||||
static TEST_REF: &u8 = unsafe { &DATA };
|
||||
|
||||
fn main() {}
|
15
tests/ui/consts/miri_unleashed/extern-static.stderr
Normal file
15
tests/ui/consts/miri_unleashed/extern-static.stderr
Normal file
|
@ -0,0 +1,15 @@
|
|||
error[E0080]: could not evaluate static initializer
|
||||
--> $DIR/extern-static.rs:11:25
|
||||
|
|
||||
LL | unsafe { let _val = DATA; }
|
||||
| ^^^^ cannot access extern static (DefId(0:4 ~ extern_static[c41e]::{extern#0}::DATA))
|
||||
|
||||
error[E0080]: could not evaluate static initializer
|
||||
--> $DIR/extern-static.rs:16:14
|
||||
|
|
||||
LL | unsafe { DATA = 0; }
|
||||
| ^^^^^^^^ cannot access extern static (DefId(0:4 ~ extern_static[c41e]::{extern#0}::DATA))
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
|
@ -14,6 +14,8 @@ static TEST_BAD: () = {
|
|||
};
|
||||
|
||||
// Make sure we catch taking a reference to thread-local storage.
|
||||
// The actual pointer depends on the thread, so even just taking a reference already does not make
|
||||
// sense at compile-time.
|
||||
static TEST_BAD_REF: () = {
|
||||
unsafe { let _val = &A; }
|
||||
//~^ ERROR could not evaluate static initializer
|
||||
|
|
|
@ -5,7 +5,7 @@ LL | unsafe { let _val = A; }
|
|||
| ^ cannot access thread local static (DefId(0:4 ~ tls[ca29]::A))
|
||||
|
||||
error[E0080]: could not evaluate static initializer
|
||||
--> $DIR/tls.rs:18:26
|
||||
--> $DIR/tls.rs:20:26
|
||||
|
|
||||
LL | unsafe { let _val = &A; }
|
||||
| ^ cannot access thread local static (DefId(0:4 ~ tls[ca29]::A))
|
||||
|
@ -18,7 +18,7 @@ help: skipping check that does not even have a feature gate
|
|||
LL | unsafe { let _val = A; }
|
||||
| ^
|
||||
help: skipping check that does not even have a feature gate
|
||||
--> $DIR/tls.rs:18:26
|
||||
--> $DIR/tls.rs:20:26
|
||||
|
|
||||
LL | unsafe { let _val = &A; }
|
||||
| ^
|
||||
|
|
|
@ -9,8 +9,6 @@ fn foo<T>(x: T) {
|
|||
(y: T) { //~ ERROR E0401
|
||||
}
|
||||
bfnr(x);
|
||||
//~^ ERROR type annotations needed
|
||||
//~| ERROR type annotations needed
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ LL | (y: T) {
|
|||
| ^ use of generic parameter from outer item
|
||||
|
||||
error[E0401]: can't use `Self` from outer item
|
||||
--> $DIR/E0401.rs:24:25
|
||||
--> $DIR/E0401.rs:22:25
|
||||
|
|
||||
LL | impl<T> Iterator for A<T> {
|
||||
| ---- `Self` type implicitly declared here, by this `impl`
|
||||
|
@ -32,45 +32,6 @@ LL | fn helper(sel: &Self) -> u8 {
|
|||
| use of `Self` from outer item
|
||||
| refer to the type directly here instead
|
||||
|
||||
error[E0283]: type annotations needed
|
||||
--> $DIR/E0401.rs:11:5
|
||||
|
|
||||
LL | bfnr(x);
|
||||
| ^^^^ cannot infer type of the type parameter `V` declared on the function `bfnr`
|
||||
|
|
||||
= note: cannot satisfy `_: Baz<_>`
|
||||
note: required by a bound in `bfnr`
|
||||
--> $DIR/E0401.rs:4:19
|
||||
|
|
||||
LL | fn bfnr<U, V: Baz<U>, W: Fn()>(y: T) {
|
||||
| ^^^^^^ required by this bound in `bfnr`
|
||||
help: consider specifying the generic arguments
|
||||
|
|
||||
LL | bfnr::<U, V, W>(x);
|
||||
| +++++++++++
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
error[E0283]: type annotations needed
|
||||
--> $DIR/E0401.rs:11:5
|
||||
|
|
||||
LL | bfnr(x);
|
||||
| ^^^^ cannot infer type of the type parameter `W` declared on the function `bfnr`
|
||||
|
|
||||
= note: multiple `impl`s satisfying `_: Fn()` found in the following crates: `alloc`, `core`:
|
||||
- impl<A, F> Fn<A> for &F
|
||||
where A: Tuple, F: Fn<A>, F: ?Sized;
|
||||
- impl<Args, F, A> Fn<Args> for Box<F, A>
|
||||
where Args: Tuple, F: Fn<Args>, A: Allocator, F: ?Sized;
|
||||
note: required by a bound in `bfnr`
|
||||
--> $DIR/E0401.rs:4:30
|
||||
|
|
||||
LL | fn bfnr<U, V: Baz<U>, W: Fn()>(y: T) {
|
||||
| ^^^^ required by this bound in `bfnr`
|
||||
help: consider specifying the generic arguments
|
||||
|
|
||||
LL | bfnr::<U, V, W>(x);
|
||||
| +++++++++++
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0283, E0401.
|
||||
For more information about an error, try `rustc --explain E0283`.
|
||||
For more information about this error, try `rustc --explain E0401`.
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
#![deny(large_assignments)]
|
||||
#![feature(large_assignments)]
|
||||
#![move_size_limit = "1000"]
|
||||
// build-fail
|
||||
// only-x86_64
|
||||
|
||||
// edition:2018
|
||||
// compile-flags: -Zmir-opt-level=0
|
||||
|
||||
use std::{sync::Arc, rc::Rc};
|
||||
|
||||
fn main() {
|
||||
let _ = Arc::new([0; 9999]); // OK!
|
||||
let _ = Box::new([0; 9999]); // OK!
|
||||
let _ = Rc::new([0; 9999]); // OK!
|
||||
let _ = NotBox::new([0; 9999]); //~ ERROR large_assignments
|
||||
}
|
||||
|
||||
struct NotBox {
|
||||
data: [u8; 9999],
|
||||
}
|
||||
|
||||
impl NotBox {
|
||||
fn new(data: [u8; 9999]) -> Self {
|
||||
Self {
|
||||
data, //~ ERROR large_assignments
|
||||
}
|
||||
}
|
||||
}
|
38
tests/ui/lint/large_assignments/copy_into_box_rc_arc.rs
Normal file
38
tests/ui/lint/large_assignments/copy_into_box_rc_arc.rs
Normal file
|
@ -0,0 +1,38 @@
|
|||
#![deny(large_assignments)]
|
||||
#![feature(large_assignments)]
|
||||
#![move_size_limit = "1000"]
|
||||
// build-fail
|
||||
// only-64bit
|
||||
|
||||
// edition:2018
|
||||
// compile-flags: -Zmir-opt-level=1
|
||||
|
||||
use std::{sync::Arc, rc::Rc};
|
||||
|
||||
fn main() {
|
||||
let data = [0; 9999];
|
||||
|
||||
// Looking at --emit mir, we can see that all parameters below are passed by
|
||||
// copy. But it requires at least mir-opt-level=1.
|
||||
let _ = Arc::new(data); // OK!
|
||||
let _ = Box::new(data); // OK!
|
||||
let _ = Rc::new(data); // OK!
|
||||
|
||||
// Looking at --emit llvm-ir, we can see that a memcpy is involved in the
|
||||
// parameter passing. So we want the lint to trigger here.
|
||||
let _ = NotBox::new(data); //~ ERROR large_assignments
|
||||
}
|
||||
|
||||
struct NotBox {
|
||||
data: [u8; 9999],
|
||||
}
|
||||
|
||||
impl NotBox {
|
||||
fn new(data: [u8; 9999]) -> Self {
|
||||
// Looking at --emit llvm-ir, we can see that a memcpy is involved.
|
||||
// So we want the lint to trigger here.
|
||||
Self { //~ ERROR large_assignments
|
||||
data,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,21 +1,23 @@
|
|||
error: moving 9999 bytes
|
||||
--> $DIR/box_rc_arc_allowed.rs:16:25
|
||||
--> $DIR/copy_into_box_rc_arc.rs:23:25
|
||||
|
|
||||
LL | let _ = NotBox::new([0; 9999]);
|
||||
| ^^^^^^^^^ value moved from here
|
||||
LL | let _ = NotBox::new(data);
|
||||
| ^^^^ value moved from here
|
||||
|
|
||||
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
|
||||
note: the lint level is defined here
|
||||
--> $DIR/box_rc_arc_allowed.rs:1:9
|
||||
--> $DIR/copy_into_box_rc_arc.rs:1:9
|
||||
|
|
||||
LL | #![deny(large_assignments)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: moving 9999 bytes
|
||||
--> $DIR/box_rc_arc_allowed.rs:26:13
|
||||
--> $DIR/copy_into_box_rc_arc.rs:34:9
|
||||
|
|
||||
LL | data,
|
||||
| ^^^^ value moved from here
|
||||
LL | / Self {
|
||||
LL | | data,
|
||||
LL | | }
|
||||
| |_________^ value moved from here
|
||||
|
|
||||
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
#![cfg_attr(attribute, feature(large_assignments))]
|
||||
#![cfg_attr(attribute, move_size_limit = "1000")]
|
||||
// build-fail
|
||||
// only-x86_64
|
||||
// only-64bit
|
||||
// revisions: attribute option
|
||||
// [option]compile-flags: -Zmove-size-limit=1000
|
||||
|
||||
|
|
38
tests/ui/lint/large_assignments/move_into_box_rc_arc.rs
Normal file
38
tests/ui/lint/large_assignments/move_into_box_rc_arc.rs
Normal file
|
@ -0,0 +1,38 @@
|
|||
#![deny(large_assignments)]
|
||||
#![feature(large_assignments)]
|
||||
#![move_size_limit = "1000"]
|
||||
// build-fail
|
||||
// only-64bit
|
||||
|
||||
// edition:2018
|
||||
// compile-flags: -Zmir-opt-level=0
|
||||
|
||||
use std::{sync::Arc, rc::Rc};
|
||||
|
||||
fn main() {
|
||||
// Looking at --emit mir, we can see that all parameters below are passed
|
||||
// by move.
|
||||
let _ = Arc::new([0; 9999]); // OK!
|
||||
let _ = Box::new([0; 9999]); // OK!
|
||||
let _ = Rc::new([0; 9999]); // OK!
|
||||
|
||||
// Looking at --emit llvm-ir, we can see that no memcpy is involved in the
|
||||
// parameter passing. Instead, a pointer is passed. This is typically what
|
||||
// we get when moving parameter into functions. So we don't want the lint to
|
||||
// trigger here.
|
||||
let _ = NotBox::new([0; 9999]); // OK (compare with copy_into_box_rc_arc.rs)
|
||||
}
|
||||
|
||||
struct NotBox {
|
||||
data: [u8; 9999],
|
||||
}
|
||||
|
||||
impl NotBox {
|
||||
fn new(data: [u8; 9999]) -> Self {
|
||||
Self {
|
||||
// Looking at --emit llvm-ir, we can see that a memcpy is involved.
|
||||
// So we want the lint to trigger here.
|
||||
data, //~ ERROR large_assignments
|
||||
}
|
||||
}
|
||||
}
|
15
tests/ui/lint/large_assignments/move_into_box_rc_arc.stderr
Normal file
15
tests/ui/lint/large_assignments/move_into_box_rc_arc.stderr
Normal file
|
@ -0,0 +1,15 @@
|
|||
error: moving 9999 bytes
|
||||
--> $DIR/move_into_box_rc_arc.rs:35:13
|
||||
|
|
||||
LL | data,
|
||||
| ^^^^ value moved from here
|
||||
|
|
||||
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
|
||||
note: the lint level is defined here
|
||||
--> $DIR/move_into_box_rc_arc.rs:1:9
|
||||
|
|
||||
LL | #![deny(large_assignments)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
22
tests/ui/lint/large_assignments/move_into_fn.rs
Normal file
22
tests/ui/lint/large_assignments/move_into_fn.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
// build-fail
|
||||
|
||||
#![feature(large_assignments)]
|
||||
#![move_size_limit = "1000"]
|
||||
#![deny(large_assignments)]
|
||||
#![allow(unused)]
|
||||
|
||||
// Note: This type does not implement Copy.
|
||||
struct Data([u8; 9999]);
|
||||
|
||||
fn main() {
|
||||
// Looking at llvm-ir output, we can see a memcpy'd into Data, so we want
|
||||
// the lint to trigger here.
|
||||
let data = Data([100; 9999]); //~ ERROR large_assignments
|
||||
|
||||
// Looking at llvm-ir output, we can see that there is no memcpy involved in
|
||||
// this function call. Instead, just a pointer is passed to the function. So
|
||||
// the lint shall not trigger here.
|
||||
take_data(data);
|
||||
}
|
||||
|
||||
fn take_data(data: Data) {}
|
15
tests/ui/lint/large_assignments/move_into_fn.stderr
Normal file
15
tests/ui/lint/large_assignments/move_into_fn.stderr
Normal file
|
@ -0,0 +1,15 @@
|
|||
error: moving 9999 bytes
|
||||
--> $DIR/move_into_fn.rs:14:16
|
||||
|
|
||||
LL | let data = Data([100; 9999]);
|
||||
| ^^^^^^^^^^^^^^^^^ value moved from here
|
||||
|
|
||||
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
|
||||
note: the lint level is defined here
|
||||
--> $DIR/move_into_fn.rs:5:9
|
||||
|
|
||||
LL | #![deny(large_assignments)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
20
tests/ui/proc-macro/auxiliary/issue-118809.rs
Normal file
20
tests/ui/proc-macro/auxiliary/issue-118809.rs
Normal file
|
@ -0,0 +1,20 @@
|
|||
// force-host
|
||||
// no-prefer-dynamic
|
||||
|
||||
#![crate_type = "proc-macro"]
|
||||
|
||||
extern crate proc_macro;
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
#[proc_macro_derive(Deserialize)]
|
||||
pub fn deserialize_derive(input: TokenStream) -> TokenStream {
|
||||
"impl Build {
|
||||
fn deserialize() -> Option<u64> {
|
||||
let x: Option<u32> = Some(0);
|
||||
Some(x? + 1)
|
||||
}
|
||||
}
|
||||
"
|
||||
.parse()
|
||||
.unwrap()
|
||||
}
|
10
tests/ui/proc-macro/issue-118809.rs
Normal file
10
tests/ui/proc-macro/issue-118809.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
// aux-build: issue-118809.rs
|
||||
|
||||
#[macro_use]
|
||||
extern crate issue_118809;
|
||||
|
||||
#[derive(Deserialize)] //~ ERROR mismatched types [E0308]
|
||||
pub struct Build {
|
||||
}
|
||||
|
||||
fn main() {}
|
21
tests/ui/proc-macro/issue-118809.stderr
Normal file
21
tests/ui/proc-macro/issue-118809.stderr
Normal file
|
@ -0,0 +1,21 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-118809.rs:6:10
|
||||
|
|
||||
LL | #[derive(Deserialize)]
|
||||
| ^^^^^^^^^^^
|
||||
| |
|
||||
| expected `u64`, found `u32`
|
||||
| arguments to this enum variant are incorrect
|
||||
|
|
||||
help: the type constructed contains `u32` due to the type of the argument passed
|
||||
--> $DIR/issue-118809.rs:6:10
|
||||
|
|
||||
LL | #[derive(Deserialize)]
|
||||
| ^^^^^^^^^^^ this argument influences the type of `Some`
|
||||
note: tuple variant defined here
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
= note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
|
@ -18,16 +18,16 @@ help: use parentheses to call this function
|
|||
LL | bar(foo());
|
||||
| ++
|
||||
|
||||
error[E0277]: `{coroutine-closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future
|
||||
error[E0277]: `{async closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future
|
||||
--> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:12:9
|
||||
|
|
||||
LL | bar(async_closure);
|
||||
| --- ^^^^^^^^^^^^^ `{coroutine-closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future
|
||||
| --- ^^^^^^^^^^^^^ `{async closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}` is not a future
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `Future` is not implemented for `{coroutine-closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}`
|
||||
= note: {coroutine-closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33} must be a future or must implement `IntoFuture` to be awaited
|
||||
= help: the trait `Future` is not implemented for `{async closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33}`
|
||||
= note: {async closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33} must be a future or must implement `IntoFuture` to be awaited
|
||||
note: required by a bound in `bar`
|
||||
--> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16
|
||||
|
|
||||
|
|
|
@ -17,4 +17,13 @@ trait InsufficientlyConstrainedGeneric<X=()> where X: std::marker::Copy {
|
|||
}
|
||||
}
|
||||
|
||||
// Regression test for #120838
|
||||
#[allow(dead_code)]
|
||||
trait InsufficientlyConstrainedGenericWithEmptyWhere<X=()> where X: std::marker::Copy {
|
||||
fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
|
||||
//~^ ERROR the trait bound `X: Copy` is not satisfied
|
||||
ConstrainedStruct { x }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() { }
|
||||
|
|
|
@ -17,4 +17,13 @@ trait InsufficientlyConstrainedGeneric<X=()> {
|
|||
}
|
||||
}
|
||||
|
||||
// Regression test for #120838
|
||||
#[allow(dead_code)]
|
||||
trait InsufficientlyConstrainedGenericWithEmptyWhere<X=()> where {
|
||||
fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
|
||||
//~^ ERROR the trait bound `X: Copy` is not satisfied
|
||||
ConstrainedStruct { x }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() { }
|
||||
|
|
|
@ -14,6 +14,22 @@ help: consider further restricting type parameter `X`
|
|||
LL | trait InsufficientlyConstrainedGeneric<X=()> where X: std::marker::Copy {
|
||||
| ++++++++++++++++++++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
error[E0277]: the trait bound `X: Copy` is not satisfied
|
||||
--> $DIR/trait-impl-bound-suggestions.rs:23:52
|
||||
|
|
||||
LL | fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `X`
|
||||
|
|
||||
note: required by a bound in `ConstrainedStruct`
|
||||
--> $DIR/trait-impl-bound-suggestions.rs:8:29
|
||||
|
|
||||
LL | struct ConstrainedStruct<X: Copy> {
|
||||
| ^^^^ required by this bound in `ConstrainedStruct`
|
||||
help: consider further restricting type parameter `X`
|
||||
|
|
||||
LL | trait InsufficientlyConstrainedGenericWithEmptyWhere<X=()> where X: std::marker::Copy {
|
||||
| ++++++++++++++++++++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
@ -6,7 +6,7 @@ struct W<T: ?Sized>(Oops);
|
|||
|
||||
unsafe fn test() {
|
||||
let j = W(());
|
||||
let pointer = &j as *const _; //~ ERROR type annotations needed
|
||||
let pointer = &j as *const _;
|
||||
core::arch::asm!(
|
||||
"nop",
|
||||
in("eax") pointer,
|
||||
|
|
|
@ -4,18 +4,6 @@ error[E0412]: cannot find type `Oops` in this scope
|
|||
LL | struct W<T: ?Sized>(Oops);
|
||||
| ^^^^ not found in this scope
|
||||
|
||||
error[E0282]: type annotations needed for `*const W<T>`
|
||||
--> $DIR/issue-104510-ice.rs:9:9
|
||||
|
|
||||
LL | let pointer = &j as *const _;
|
||||
| ^^^^^^^
|
||||
|
|
||||
help: consider giving `pointer` an explicit type, where the type for type parameter `T` is specified
|
||||
|
|
||||
LL | let pointer: *const W<T> = &j as *const _;
|
||||
| +++++++++++++
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0282, E0412.
|
||||
For more information about an error, try `rustc --explain E0282`.
|
||||
For more information about this error, try `rustc --explain E0412`.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue