Auto merge of #126274 - jieyouxu:rollup-uj93sfm, r=jieyouxu
Rollup of 5 pull requests Successful merges: - #126186 (Migrate `run-make/multiple-emits` to `rmake.rs`) - #126236 (Delegation: fix ICE on recursive delegation) - #126254 (Remove ignore-cross-compile directive from ui/macros/proc_macro) - #126258 (Do not define opaque types when selecting impls) - #126265 (interpret: ensure we check bool/char for validity when they are used in a cast) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
0c960618b5
@ -67,7 +67,9 @@ pub(crate) fn delegation_has_self(&self, item_id: NodeId, path_id: NodeId, span:
|
||||
return false;
|
||||
};
|
||||
if let Some(local_sig_id) = sig_id.as_local() {
|
||||
self.resolver.delegation_fn_sigs[&local_sig_id].has_self
|
||||
// The value may be missing due to recursive delegation.
|
||||
// Error will be emmited later during HIR ty lowering.
|
||||
self.resolver.delegation_fn_sigs.get(&local_sig_id).map_or(false, |sig| sig.has_self)
|
||||
} else {
|
||||
match self.tcx.def_kind(sig_id) {
|
||||
DefKind::Fn => false,
|
||||
|
@ -274,9 +274,13 @@ fn cast_from_int_like(
|
||||
// Let's make sure v is sign-extended *if* it has a signed type.
|
||||
let signed = src_layout.abi.is_signed(); // Also asserts that abi is `Scalar`.
|
||||
|
||||
let v = scalar.to_bits(src_layout.size)?;
|
||||
let v = if signed { self.sign_extend(v, src_layout) } else { v };
|
||||
trace!("cast_from_scalar: {}, {} -> {}", v, src_layout.ty, cast_ty);
|
||||
let v = match src_layout.ty.kind() {
|
||||
Uint(_) | RawPtr(..) | FnPtr(..) => scalar.to_uint(src_layout.size)?,
|
||||
Int(_) => scalar.to_int(src_layout.size)? as u128, // we will cast back to `i128` below if the sign matters
|
||||
Bool => scalar.to_bool()?.into(),
|
||||
Char => scalar.to_char()?.into(),
|
||||
_ => span_bug!(self.cur_span(), "invalid int-like cast from {}", src_layout.ty),
|
||||
};
|
||||
|
||||
Ok(match *cast_ty.kind() {
|
||||
// int -> int
|
||||
|
@ -197,7 +197,7 @@ pub fn emulate_intrinsic(
|
||||
// rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
|
||||
let layout_val = self.layout_of(instance_args.type_at(0))?;
|
||||
let val = self.read_scalar(&args[0])?;
|
||||
let val_bits = val.to_bits(layout_val.size)?;
|
||||
let val_bits = val.to_bits(layout_val.size)?; // sign is ignored here
|
||||
|
||||
let layout_raw_shift = self.layout_of(self.tcx.types.u32)?;
|
||||
let raw_shift = self.read_scalar(&args[1])?;
|
||||
@ -484,7 +484,7 @@ pub fn numeric_intrinsic(
|
||||
ret_layout: TyAndLayout<'tcx>,
|
||||
) -> InterpResult<'tcx, Scalar<M::Provenance>> {
|
||||
assert!(layout.ty.is_integral(), "invalid type for numeric intrinsic: {}", layout.ty);
|
||||
let bits = val.to_bits(layout.size)?;
|
||||
let bits = val.to_bits(layout.size)?; // these operations all ignore the sign
|
||||
let extra = 128 - u128::from(layout.size.bits());
|
||||
let bits_out = match name {
|
||||
sym::ctpop => u128::from(bits.count_ones()),
|
||||
@ -519,6 +519,7 @@ pub fn exact_div(
|
||||
// `x % y != 0` or `y == 0` or `x == T::MIN && y == -1`.
|
||||
// First, check x % y != 0 (or if that computation overflows).
|
||||
let rem = self.binary_op(BinOp::Rem, a, b)?;
|
||||
// sign does not matter for 0 test, so `to_bits` is fine
|
||||
if rem.to_scalar().to_bits(a.layout.size)? != 0 {
|
||||
throw_ub_custom!(
|
||||
fluent::const_eval_exact_div_has_remainder,
|
||||
@ -545,22 +546,19 @@ pub fn saturating_arith(
|
||||
self.binary_op(mir_op.wrapping_to_overflowing().unwrap(), l, r)?.to_scalar_pair();
|
||||
Ok(if overflowed.to_bool()? {
|
||||
let size = l.layout.size;
|
||||
let num_bits = size.bits();
|
||||
if l.layout.abi.is_signed() {
|
||||
// For signed ints the saturated value depends on the sign of the first
|
||||
// term since the sign of the second term can be inferred from this and
|
||||
// the fact that the operation has overflowed (if either is 0 no
|
||||
// overflow can occur)
|
||||
let first_term: u128 = l.to_scalar().to_bits(l.layout.size)?;
|
||||
let first_term_positive = first_term & (1 << (num_bits - 1)) == 0;
|
||||
if first_term_positive {
|
||||
let first_term: i128 = l.to_scalar().to_int(l.layout.size)?;
|
||||
if first_term >= 0 {
|
||||
// Negative overflow not possible since the positive first term
|
||||
// can only increase an (in range) negative term for addition
|
||||
// or corresponding negated positive term for subtraction
|
||||
// or corresponding negated positive term for subtraction.
|
||||
Scalar::from_int(size.signed_int_max(), size)
|
||||
} else {
|
||||
// Positive overflow not possible for similar reason
|
||||
// max negative
|
||||
// Positive overflow not possible for similar reason.
|
||||
Scalar::from_int(size.signed_int_min(), size)
|
||||
}
|
||||
} else {
|
||||
|
@ -437,23 +437,24 @@ pub fn unary_op(
|
||||
};
|
||||
Ok(ImmTy::from_scalar(res, layout))
|
||||
}
|
||||
_ if layout.ty.is_integral() => {
|
||||
let val = val.to_scalar();
|
||||
let val = val.to_bits(layout.size)?;
|
||||
ty::Int(..) => {
|
||||
let val = val.to_scalar().to_int(layout.size)?;
|
||||
let res = match un_op {
|
||||
Not => self.truncate(!val, layout), // bitwise negation, then truncate
|
||||
Neg => {
|
||||
// arithmetic negation
|
||||
assert!(layout.abi.is_signed());
|
||||
let val = self.sign_extend(val, layout) as i128;
|
||||
let res = val.wrapping_neg();
|
||||
let res = res as u128;
|
||||
// Truncate to target type.
|
||||
self.truncate(res, layout)
|
||||
}
|
||||
Not => !val,
|
||||
Neg => val.wrapping_neg(),
|
||||
_ => span_bug!(self.cur_span(), "Invalid integer op {:?}", un_op),
|
||||
};
|
||||
Ok(ImmTy::from_uint(res, layout))
|
||||
let res = ScalarInt::truncate_from_int(res, layout.size).0;
|
||||
Ok(ImmTy::from_scalar(res.into(), layout))
|
||||
}
|
||||
ty::Uint(..) => {
|
||||
let val = val.to_scalar().to_uint(layout.size)?;
|
||||
let res = match un_op {
|
||||
Not => !val,
|
||||
_ => span_bug!(self.cur_span(), "Invalid unsigned integer op {:?}", un_op),
|
||||
};
|
||||
let res = ScalarInt::truncate_from_uint(res, layout.size).0;
|
||||
Ok(ImmTy::from_scalar(res.into(), layout))
|
||||
}
|
||||
ty::RawPtr(..) => {
|
||||
assert_eq!(un_op, PtrMetadata);
|
||||
|
@ -209,8 +209,8 @@ pub fn is_null(self) -> bool {
|
||||
|
||||
#[inline]
|
||||
pub fn try_from_uint(i: impl Into<u128>, size: Size) -> Option<Self> {
|
||||
let data = i.into();
|
||||
if size.truncate(data) == data { Some(Self::raw(data, size)) } else { None }
|
||||
let (r, overflow) = Self::truncate_from_uint(i, size);
|
||||
if overflow { None } else { Some(r) }
|
||||
}
|
||||
|
||||
/// Returns the truncated result, and whether truncation changed the value.
|
||||
@ -223,20 +223,15 @@ pub fn truncate_from_uint(i: impl Into<u128>, size: Size) -> (Self, bool) {
|
||||
|
||||
#[inline]
|
||||
pub fn try_from_int(i: impl Into<i128>, size: Size) -> Option<Self> {
|
||||
let i = i.into();
|
||||
// `into` performed sign extension, we have to truncate
|
||||
let truncated = size.truncate(i as u128);
|
||||
if size.sign_extend(truncated) as i128 == i {
|
||||
Some(Self::raw(truncated, size))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
let (r, overflow) = Self::truncate_from_int(i, size);
|
||||
if overflow { None } else { Some(r) }
|
||||
}
|
||||
|
||||
/// Returns the truncated result, and whether truncation changed the value.
|
||||
#[inline]
|
||||
pub fn truncate_from_int(i: impl Into<i128>, size: Size) -> (Self, bool) {
|
||||
let data = i.into();
|
||||
// `into` performed sign extension, we have to truncate
|
||||
let r = Self::raw(size.truncate(data as u128), size);
|
||||
(r, size.sign_extend(r.data) as i128 != data)
|
||||
}
|
||||
|
@ -2563,7 +2563,7 @@ fn match_impl(
|
||||
let InferOk { obligations, .. } = self
|
||||
.infcx
|
||||
.at(&cause, obligation.param_env)
|
||||
.eq(DefineOpaqueTypes::Yes, placeholder_obligation_trait_ref, impl_trait_ref)
|
||||
.eq(DefineOpaqueTypes::No, placeholder_obligation_trait_ref, impl_trait_ref)
|
||||
.map_err(|e| {
|
||||
debug!("match_impl: failed eq_trait_refs due to `{}`", e.to_string(self.tcx()))
|
||||
})?;
|
||||
|
21
src/tools/miri/tests/fail/validity/invalid_char_cast.rs
Normal file
21
src/tools/miri/tests/fail/validity/invalid_char_cast.rs
Normal file
@ -0,0 +1,21 @@
|
||||
// Make sure we find these even with many checks disabled.
|
||||
//@compile-flags: -Zmiri-disable-alignment-check -Zmiri-disable-stacked-borrows -Zmiri-disable-validation
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(custom_mir)]
|
||||
|
||||
use std::intrinsics::mir::*;
|
||||
|
||||
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
||||
fn cast(ptr: *const char) -> u32 {
|
||||
mir! {
|
||||
{
|
||||
RET = *ptr as u32; //~ERROR: interpreting an invalid 32-bit value as a char
|
||||
Return()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let v = u32::MAX;
|
||||
cast(&v as *const u32 as *const char);
|
||||
}
|
20
src/tools/miri/tests/fail/validity/invalid_char_cast.stderr
Normal file
20
src/tools/miri/tests/fail/validity/invalid_char_cast.stderr
Normal file
@ -0,0 +1,20 @@
|
||||
error: Undefined Behavior: interpreting an invalid 32-bit value as a char: $HEX
|
||||
--> $DIR/invalid_char_cast.rs:LL:CC
|
||||
|
|
||||
LL | RET = *ptr as u32;
|
||||
| ^^^^^^^^^^^^^^^^^ interpreting an invalid 32-bit value as a char: $HEX
|
||||
|
|
||||
= 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 `cast` at $DIR/invalid_char_cast.rs:LL:CC
|
||||
note: inside `main`
|
||||
--> $DIR/invalid_char_cast.rs:LL:CC
|
||||
|
|
||||
LL | cast(&v as *const u32 as *const char);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
26
src/tools/miri/tests/fail/validity/invalid_char_match.rs
Normal file
26
src/tools/miri/tests/fail/validity/invalid_char_match.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// Make sure we find these even with many checks disabled.
|
||||
//@compile-flags: -Zmiri-disable-alignment-check -Zmiri-disable-stacked-borrows -Zmiri-disable-validation
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(custom_mir)]
|
||||
|
||||
use std::intrinsics::mir::*;
|
||||
|
||||
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
||||
fn switch_int(ptr: *const char) {
|
||||
mir! {
|
||||
{
|
||||
match *ptr { //~ERROR: interpreting an invalid 32-bit value as a char
|
||||
'0' => ret,
|
||||
_ => ret,
|
||||
}
|
||||
}
|
||||
ret = {
|
||||
Return()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let v = u32::MAX;
|
||||
switch_int(&v as *const u32 as *const char);
|
||||
}
|
23
src/tools/miri/tests/fail/validity/invalid_char_match.stderr
Normal file
23
src/tools/miri/tests/fail/validity/invalid_char_match.stderr
Normal file
@ -0,0 +1,23 @@
|
||||
error: Undefined Behavior: interpreting an invalid 32-bit value as a char: $HEX
|
||||
--> $DIR/invalid_char_match.rs:LL:CC
|
||||
|
|
||||
LL | / match *ptr {
|
||||
LL | | '0' => ret,
|
||||
LL | | _ => ret,
|
||||
LL | | }
|
||||
| |_____________^ interpreting an invalid 32-bit value as a char: $HEX
|
||||
|
|
||||
= 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 `switch_int` at $DIR/invalid_char_match.rs:LL:CC
|
||||
note: inside `main`
|
||||
--> $DIR/invalid_char_match.rs:LL:CC
|
||||
|
|
||||
LL | switch_int(&v as *const u32 as *const char);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
15
src/tools/miri/tests/fail/validity/invalid_enum_cast.rs
Normal file
15
src/tools/miri/tests/fail/validity/invalid_enum_cast.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// Make sure we find these even with many checks disabled.
|
||||
//@compile-flags: -Zmiri-disable-alignment-check -Zmiri-disable-stacked-borrows -Zmiri-disable-validation
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[allow(unused)]
|
||||
enum E {A, B, C }
|
||||
|
||||
fn cast(ptr: *const E) { unsafe {
|
||||
let _val = *ptr as u32; //~ERROR: enum value has invalid tag
|
||||
}}
|
||||
|
||||
pub fn main() {
|
||||
let v = u32::MAX;
|
||||
cast(&v as *const u32 as *const E);
|
||||
}
|
20
src/tools/miri/tests/fail/validity/invalid_enum_cast.stderr
Normal file
20
src/tools/miri/tests/fail/validity/invalid_enum_cast.stderr
Normal file
@ -0,0 +1,20 @@
|
||||
error: Undefined Behavior: enum value has invalid tag: 0xff
|
||||
--> $DIR/invalid_enum_cast.rs:LL:CC
|
||||
|
|
||||
LL | let _val = *ptr as u32;
|
||||
| ^^^^^^^^^^^ enum value has invalid tag: 0xff
|
||||
|
|
||||
= 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 `cast` at $DIR/invalid_enum_cast.rs:LL:CC
|
||||
note: inside `main`
|
||||
--> $DIR/invalid_enum_cast.rs:LL:CC
|
||||
|
|
||||
LL | cast(&v as *const u32 as *const E);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
@ -82,6 +82,11 @@ pub fn htmldocck() -> Command {
|
||||
python
|
||||
}
|
||||
|
||||
/// Returns the path for a local test file.
|
||||
pub fn path<P: AsRef<Path>>(p: P) -> PathBuf {
|
||||
cwd().join(p.as_ref())
|
||||
}
|
||||
|
||||
/// Path to the root rust-lang/rust source checkout.
|
||||
pub fn source_root() -> PathBuf {
|
||||
env_var("SOURCE_ROOT").into()
|
||||
|
@ -144,7 +144,6 @@ run-make/mismatching-target-triples/Makefile
|
||||
run-make/missing-crate-dependency/Makefile
|
||||
run-make/mixing-libs/Makefile
|
||||
run-make/msvc-opt-minsize/Makefile
|
||||
run-make/multiple-emits/Makefile
|
||||
run-make/native-link-modifier-bundle/Makefile
|
||||
run-make/native-link-modifier-verbatim-linker/Makefile
|
||||
run-make/native-link-modifier-verbatim-rustc/Makefile
|
||||
|
@ -1,4 +0,0 @@
|
||||
//@ known-bug: #124347
|
||||
trait Trait: ToReuse {
|
||||
reuse Trait::lolno { &self.0 };
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
include ../tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTC) foo.rs --emit=asm,llvm-ir -o $(TMPDIR)/out 2>&1
|
||||
rm $(TMPDIR)/out.ll $(TMPDIR)/out.s
|
||||
$(RUSTC) foo.rs --emit=asm,llvm-ir -o $(TMPDIR)/out2.ext 2>&1
|
||||
rm $(TMPDIR)/out2.ll $(TMPDIR)/out2.s
|
13
tests/run-make/multiple-emits/rmake.rs
Normal file
13
tests/run-make/multiple-emits/rmake.rs
Normal file
@ -0,0 +1,13 @@
|
||||
use run_make_support::{cwd, path, rustc};
|
||||
|
||||
fn main() {
|
||||
rustc().input("foo.rs").emit("asm,llvm-ir").output("out").run();
|
||||
|
||||
assert!(path("out.ll").is_file());
|
||||
assert!(path("out.s").is_file());
|
||||
|
||||
rustc().input("foo.rs").emit("asm,llvm-ir").output("out2.ext").run();
|
||||
|
||||
assert!(path("out2.ll").is_file());
|
||||
assert!(path("out2.s").is_file());
|
||||
}
|
11
tests/ui/consts/const-eval/ub-invalid-values.rs
Normal file
11
tests/ui/consts/const-eval/ub-invalid-values.rs
Normal file
@ -0,0 +1,11 @@
|
||||
const fn bool_cast(ptr: *const bool) { unsafe {
|
||||
let _val = *ptr as u32; //~ERROR: evaluation of constant value failed
|
||||
//~^ interpreting an invalid 8-bit value as a bool
|
||||
}}
|
||||
|
||||
const _: () = {
|
||||
let v = 3_u8;
|
||||
bool_cast(&v as *const u8 as *const bool);
|
||||
};
|
||||
|
||||
fn main() {}
|
20
tests/ui/consts/const-eval/ub-invalid-values.stderr
Normal file
20
tests/ui/consts/const-eval/ub-invalid-values.stderr
Normal file
@ -0,0 +1,20 @@
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/ub-invalid-values.rs:2:16
|
||||
|
|
||||
LL | let _val = *ptr as u32;
|
||||
| ^^^^^^^^^^^ interpreting an invalid 8-bit value as a bool: 0x03
|
||||
|
|
||||
note: inside `bool_cast`
|
||||
--> $DIR/ub-invalid-values.rs:2:16
|
||||
|
|
||||
LL | let _val = *ptr as u32;
|
||||
| ^^^^^^^^^^^
|
||||
note: inside `_`
|
||||
--> $DIR/ub-invalid-values.rs:8:5
|
||||
|
|
||||
LL | bool_cast(&v as *const u8 as *const bool);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
12
tests/ui/delegation/ice-issue-124347.rs
Normal file
12
tests/ui/delegation/ice-issue-124347.rs
Normal file
@ -0,0 +1,12 @@
|
||||
#![feature(fn_delegation)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
trait Trait {
|
||||
reuse Trait::foo { &self.0 }
|
||||
//~^ ERROR recursive delegation is not supported yet
|
||||
}
|
||||
|
||||
reuse foo;
|
||||
//~^ ERROR recursive delegation is not supported yet
|
||||
|
||||
fn main() {}
|
14
tests/ui/delegation/ice-issue-124347.stderr
Normal file
14
tests/ui/delegation/ice-issue-124347.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error: recursive delegation is not supported yet
|
||||
--> $DIR/ice-issue-124347.rs:5:18
|
||||
|
|
||||
LL | reuse Trait::foo { &self.0 }
|
||||
| ^^^ callee defined here
|
||||
|
||||
error: recursive delegation is not supported yet
|
||||
--> $DIR/ice-issue-124347.rs:9:7
|
||||
|
|
||||
LL | reuse foo;
|
||||
| ^^^ callee defined here
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -22,7 +22,7 @@ fn sum_to(n: u32) -> impl Foo {
|
||||
0
|
||||
} else {
|
||||
n + sum_to(n - 1)
|
||||
//~^ ERROR cannot satisfy `<u32 as Add<impl Foo>>::Output == i32`
|
||||
//~^ ERROR cannot add `impl Foo` to `u32`
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,15 +32,12 @@ trait Leak: Sized {
|
||||
}
|
||||
impl<T> Leak for T {
|
||||
default type T = ();
|
||||
default fn leak(self) -> Self::T {
|
||||
panic!()
|
||||
}
|
||||
default fn leak(self) -> Self::T { panic!() }
|
||||
}
|
||||
impl Leak for i32 {
|
||||
type T = i32;
|
||||
fn leak(self) -> i32 {
|
||||
self
|
||||
}
|
||||
fn leak(self) -> i32 { self }
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
fn main() {
|
||||
}
|
||||
|
@ -22,13 +22,20 @@ help: change the type of the numeric literal from `u32` to `i32`
|
||||
LL | 0_i32
|
||||
| ~~~
|
||||
|
||||
error[E0284]: type annotations needed: cannot satisfy `<u32 as Add<impl Foo>>::Output == i32`
|
||||
error[E0277]: cannot add `impl Foo` to `u32`
|
||||
--> $DIR/equality.rs:24:11
|
||||
|
|
||||
LL | n + sum_to(n - 1)
|
||||
| ^ cannot satisfy `<u32 as Add<impl Foo>>::Output == i32`
|
||||
| ^ no implementation for `u32 + impl Foo`
|
||||
|
|
||||
= help: the trait `Add<impl Foo>` is not implemented for `u32`
|
||||
= help: the following other types implement trait `Add<Rhs>`:
|
||||
<&'a u32 as Add<u32>>
|
||||
<&u32 as Add<&u32>>
|
||||
<u32 as Add<&u32>>
|
||||
<u32 as Add>
|
||||
|
||||
error: aborting due to 2 previous errors; 1 warning emitted
|
||||
|
||||
Some errors have detailed explanations: E0284, E0308.
|
||||
For more information about an error, try `rustc --explain E0284`.
|
||||
Some errors have detailed explanations: E0277, E0308.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
@ -46,23 +46,19 @@ error[E0277]: the trait bound `impl Into<u32>: Into<impl Debug>` is not satisfie
|
||||
--> $DIR/nested_impl_trait.rs:6:46
|
||||
|
|
||||
LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `impl Into<u32>`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Into<u32>`, which is required by `impl Into<u32>: Into<impl Debug>`
|
||||
|
|
||||
help: consider further restricting this bound
|
||||
|
|
||||
LL | fn bad_in_ret_position(x: impl Into<u32> + std::fmt::Debug) -> impl Into<impl Debug> { x }
|
||||
| +++++++++++++++++
|
||||
= help: the trait `Into<U>` is implemented for `T`
|
||||
= note: required for `impl Into<u32>` to implement `Into<impl Debug>`
|
||||
|
||||
error[E0277]: the trait bound `impl Into<u32>: Into<impl Debug>` is not satisfied
|
||||
--> $DIR/nested_impl_trait.rs:19:34
|
||||
|
|
||||
LL | fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `impl Into<u32>`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Into<u32>`, which is required by `impl Into<u32>: Into<impl Debug>`
|
||||
|
|
||||
help: consider further restricting this bound
|
||||
|
|
||||
LL | fn bad(x: impl Into<u32> + std::fmt::Debug) -> impl Into<impl Debug> { x }
|
||||
| +++++++++++++++++
|
||||
= help: the trait `Into<U>` is implemented for `T`
|
||||
= note: required for `impl Into<u32>` to implement `Into<impl Debug>`
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
|
9
tests/ui/impl-trait/recursive-bound-eval.next.stderr
Normal file
9
tests/ui/impl-trait/recursive-bound-eval.next.stderr
Normal file
@ -0,0 +1,9 @@
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/recursive-bound-eval.rs:20:13
|
||||
|
|
||||
LL | move || recursive_fn().parse()
|
||||
| ^^^^^^^^^^^^^^ cannot infer type
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0282`.
|
24
tests/ui/impl-trait/recursive-bound-eval.rs
Normal file
24
tests/ui/impl-trait/recursive-bound-eval.rs
Normal file
@ -0,0 +1,24 @@
|
||||
//! Test that we can evaluate nested obligations when invoking methods on recursive calls on
|
||||
//! an RPIT.
|
||||
|
||||
//@revisions: next current
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
//@[current] check-pass
|
||||
|
||||
pub trait Parser<E> {
|
||||
fn parse(&self) -> E;
|
||||
}
|
||||
|
||||
impl<E, T: Fn() -> E> Parser<E> for T {
|
||||
fn parse(&self) -> E {
|
||||
self()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn recursive_fn<E>() -> impl Parser<E> {
|
||||
move || recursive_fn().parse()
|
||||
//[next]~^ ERROR: type annotations needed
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -11,7 +11,7 @@ fn eq(&self, _other: &(Bar, i32)) -> bool {
|
||||
}
|
||||
|
||||
fn foo() -> Foo {
|
||||
//~^ ERROR overflow evaluating the requirement `Bar: PartialEq<(Foo, i32)>`
|
||||
//~^ ERROR can't compare `Bar` with `(Foo, i32)`
|
||||
Bar
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,15 @@
|
||||
error[E0275]: overflow evaluating the requirement `Bar: PartialEq<(Foo, i32)>`
|
||||
error[E0277]: can't compare `Bar` with `(Foo, i32)`
|
||||
--> $DIR/recursive-type-alias-impl-trait-declaration.rs:13:13
|
||||
|
|
||||
LL | fn foo() -> Foo {
|
||||
| ^^^
|
||||
| ^^^ no implementation for `Bar == (Foo, i32)`
|
||||
LL |
|
||||
LL | Bar
|
||||
| --- return type was inferred to be `Bar` here
|
||||
|
|
||||
= help: the trait `PartialEq<(Foo, i32)>` is not implemented for `Bar`
|
||||
= help: the trait `PartialEq<(Bar, i32)>` is implemented for `Bar`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
@ -1,6 +1,5 @@
|
||||
//@ run-pass
|
||||
//@ aux-build:proc_macro_def.rs
|
||||
//@ ignore-cross-compile
|
||||
|
||||
extern crate proc_macro_def;
|
||||
|
||||
|
@ -0,0 +1,11 @@
|
||||
error[E0277]: the trait bound `Foo: Trait<Bar>` is not satisfied
|
||||
--> $DIR/constrain_in_projection.rs:24:14
|
||||
|
|
||||
LL | let x = <Foo as Trait<Bar>>::Assoc::default();
|
||||
| ^^^ the trait `Trait<Bar>` is not implemented for `Foo`
|
||||
|
|
||||
= help: the trait `Trait<()>` is implemented for `Foo`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -4,7 +4,7 @@
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@check-pass
|
||||
//@[next]check-pass
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
@ -22,6 +22,7 @@ impl Trait<()> for Foo {
|
||||
|
||||
fn bop(_: Bar) {
|
||||
let x = <Foo as Trait<Bar>>::Assoc::default();
|
||||
//[current]~^ `Foo: Trait<Bar>` is not satisfied
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,19 +1,13 @@
|
||||
error[E0283]: type annotations needed: cannot satisfy `Foo: Trait<Bar>`
|
||||
error[E0277]: the trait bound `Foo: Trait<Bar>` is not satisfied
|
||||
--> $DIR/constrain_in_projection2.rs:27:14
|
||||
|
|
||||
LL | let x = <Foo as Trait<Bar>>::Assoc::default();
|
||||
| ^^^ help: use the fully qualified path to an implementation: `<Type as Trait>::Assoc`
|
||||
| ^^^ the trait `Trait<Bar>` is not implemented for `Foo`
|
||||
|
|
||||
note: multiple `impl`s satisfying `Foo: Trait<Bar>` found
|
||||
--> $DIR/constrain_in_projection2.rs:18:1
|
||||
|
|
||||
LL | impl Trait<()> for Foo {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | impl Trait<u32> for Foo {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: associated types cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
|
||||
= help: the following other types implement trait `Trait<T>`:
|
||||
<Foo as Trait<()>>
|
||||
<Foo as Trait<u32>>
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0283`.
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
@ -25,7 +25,8 @@ impl Trait<u32> for Foo {
|
||||
|
||||
fn bop(_: Bar) {
|
||||
let x = <Foo as Trait<Bar>>::Assoc::default();
|
||||
//~^ ERROR: cannot satisfy `Foo: Trait<Bar>`
|
||||
//[next]~^ ERROR: cannot satisfy `Foo: Trait<Bar>`
|
||||
//[current]~^^ ERROR: `Foo: Trait<Bar>` is not satisfied
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -20,7 +20,7 @@ trait Trait<T, In> {
|
||||
impl<In, Out> Trait<Bar, In> for Out {
|
||||
type Out = Out;
|
||||
fn convert(_i: In) -> Self::Out {
|
||||
//[next]~^ ERROR: type annotations needed
|
||||
//[next]~^ ERROR: cannot satisfy `<Out as Trait<Bar, In>>::Out == ()`
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
error[E0277]: the trait bound `(): Foo<FooX>` is not satisfied
|
||||
--> $DIR/nested-tait-inference.rs:12:13
|
||||
--> $DIR/nested-tait-inference.rs:17:13
|
||||
|
|
||||
LL | fn foo() -> impl Foo<FooX> {
|
||||
| ^^^^^^^^^^^^^^ the trait `Foo<FooX>` is not implemented for `()`
|
@ -4,7 +4,7 @@
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@check-pass
|
||||
//@[next] check-pass
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
@ -15,6 +15,8 @@ trait Foo<A> {}
|
||||
impl Foo<()> for () {}
|
||||
|
||||
fn foo() -> impl Foo<FooX> {
|
||||
//[current]~^ ERROR: the trait bound `(): Foo<FooX>` is not satisfied
|
||||
// FIXME(type-alias-impl-trait): We could probably make this work.
|
||||
()
|
||||
}
|
||||
|
||||
|
@ -1,17 +1,16 @@
|
||||
error[E0283]: type annotations needed: cannot satisfy `(): Foo<FooX>`
|
||||
error[E0277]: the trait bound `(): Foo<FooX>` is not satisfied
|
||||
--> $DIR/nested-tait-inference2.rs:17:13
|
||||
|
|
||||
LL | fn foo() -> impl Foo<FooX> {
|
||||
| ^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^ the trait `Foo<FooX>` is not implemented for `()`
|
||||
LL |
|
||||
LL | ()
|
||||
| -- return type was inferred to be `()` here
|
||||
|
|
||||
note: multiple `impl`s satisfying `(): Foo<FooX>` found
|
||||
--> $DIR/nested-tait-inference2.rs:14:1
|
||||
|
|
||||
LL | impl Foo<()> for () {}
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
LL | impl Foo<u32> for () {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
= help: the following other types implement trait `Foo<A>`:
|
||||
<() as Foo<()>>
|
||||
<() as Foo<u32>>
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0283`.
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
@ -15,7 +15,7 @@ impl Foo<()> for () {}
|
||||
impl Foo<u32> for () {}
|
||||
|
||||
fn foo() -> impl Foo<FooX> {
|
||||
//[current]~^ ERROR: cannot satisfy `(): Foo<FooX>`
|
||||
//[current]~^ ERROR: the trait bound `(): Foo<FooX>` is not satisfied
|
||||
()
|
||||
//[next]~^ ERROR: cannot satisfy `impl Foo<FooX> == ()`
|
||||
}
|
||||
|
@ -22,17 +22,21 @@ note: previous use here
|
||||
LL | fn define_1() -> Opaque { dyn_hoops::<_>(0) }
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: concrete type differs from previous defining opaque type use
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/normalize-hidden-types.rs:43:25
|
||||
|
|
||||
LL | type Opaque = impl Sized;
|
||||
| ---------- the expected opaque type
|
||||
...
|
||||
LL | let _: Opaque = dyn_hoops::<u8>(0);
|
||||
| ^^^^^^^^^^^^^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(<u8 as Trait>::Gat<'a>)`
|
||||
| ------ ^^^^^^^^^^^^^^^^^^ expected opaque type, found `*const dyn FnOnce(())`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
note: previous use here
|
||||
--> $DIR/normalize-hidden-types.rs:44:9
|
||||
|
|
||||
LL | None
|
||||
| ^^^^
|
||||
= note: expected opaque type `typeck::Opaque`
|
||||
found raw pointer `*const (dyn FnOnce(()) + 'static)`
|
||||
= help: consider constraining the associated type `<u8 as Trait>::Gat<'_>` to `()` or calling a method that returns `<u8 as Trait>::Gat<'_>`
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
|
||||
|
||||
error: concrete type differs from previous defining opaque type use
|
||||
--> $DIR/normalize-hidden-types.rs:52:25
|
||||
@ -48,3 +52,4 @@ LL | None
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
@ -0,0 +1,14 @@
|
||||
error[E0277]: can't compare `i32` with `Foo`
|
||||
--> $DIR/self-referential-2.rs:10:13
|
||||
|
|
||||
LL | fn bar() -> Bar {
|
||||
| ^^^ no implementation for `i32 == Foo`
|
||||
LL | 42_i32
|
||||
| ------ return type was inferred to be `i32` here
|
||||
|
|
||||
= help: the trait `PartialEq<Foo>` is not implemented for `i32`
|
||||
= help: the trait `PartialEq` is implemented for `i32`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -1,14 +1,14 @@
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@ check-pass
|
||||
//@[next] check-pass
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
type Foo = impl std::fmt::Debug;
|
||||
type Bar = impl PartialEq<Foo>;
|
||||
|
||||
fn bar() -> Bar {
|
||||
42_i32
|
||||
42_i32 //[current]~^ ERROR can't compare `i32` with `Foo`
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -5,7 +5,7 @@
|
||||
type Bar<'a, 'b> = impl PartialEq<Bar<'a, 'b>> + std::fmt::Debug;
|
||||
|
||||
fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
|
||||
//~^ ERROR overflow normalizing the type alias `Bar<'a, 'b>`
|
||||
//~^ ERROR can't compare `&i32` with `Bar<'a, 'b>`
|
||||
i
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,15 @@
|
||||
error[E0275]: overflow normalizing the type alias `Bar<'a, 'b>`
|
||||
error[E0277]: can't compare `&i32` with `Bar<'a, 'b>`
|
||||
--> $DIR/self-referential-3.rs:7:31
|
||||
|
|
||||
LL | fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
|
||||
| ^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^ no implementation for `&i32 == Bar<'a, 'b>`
|
||||
LL |
|
||||
LL | i
|
||||
| - return type was inferred to be `&i32` here
|
||||
|
|
||||
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead
|
||||
= help: the trait `PartialEq<Bar<'a, 'b>>` is not implemented for `&i32`
|
||||
= help: the trait `PartialEq` is implemented for `i32`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
Loading…
Reference in New Issue
Block a user