Auto merge of #136041 - matthiaskrgr:rollup-5r1k45x, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #135971 (Properly report error when object type param default references self) - #135977 (Fix `FormattingOptions` instantiation with `Default`) - #135985 (Rename test to `unresolvable-upvar-issue-87987.rs` and add some notes) - #135991 (Fix set_name in thread mod for NuttX) - #136009 (bootstrap: Handle bootstrap lockfile race condition better) - #136018 (Use short ty string for move errors) - #136027 (Skip suggestions in `derive`d code) - #136029 (Bootstrap: Don't move ownership of job object) - #136034 (fix(bootstrap): deserialize null as `f64::NAN`) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
f94018810c
34 changed files with 274 additions and 126 deletions
|
@ -92,6 +92,9 @@ borrowck_lifetime_constraints_error =
|
|||
borrowck_limitations_implies_static =
|
||||
due to current limitations in the borrow checker, this implies a `'static` lifetime
|
||||
|
||||
borrowck_long_type_consider_verbose = consider using `--verbose` to print the full type name to the console
|
||||
borrowck_long_type_full_path = the full type name has been written to '{$path}'
|
||||
|
||||
borrowck_move_closure_suggestion =
|
||||
consider adding 'move' keyword before the nested closure
|
||||
|
||||
|
|
|
@ -289,6 +289,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
None => "value".to_owned(),
|
||||
};
|
||||
if needs_note {
|
||||
let mut path = None;
|
||||
let ty = self.infcx.tcx.short_ty_string(ty, &mut path);
|
||||
if let Some(local) = place.as_local() {
|
||||
let span = self.body.local_decls[local].source_info.span;
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
|
||||
|
@ -304,6 +306,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
place: ¬e_msg,
|
||||
});
|
||||
};
|
||||
if let Some(path) = path {
|
||||
err.subdiagnostic(crate::session_diagnostics::LongTypePath {
|
||||
path: path.display().to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if let UseSpans::FnSelfUse {
|
||||
|
|
|
@ -596,12 +596,19 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
self.suggest_cloning(err, place_ty, expr, None);
|
||||
}
|
||||
|
||||
let mut path = None;
|
||||
let ty = self.infcx.tcx.short_ty_string(place_ty, &mut path);
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
|
||||
is_partial_move: false,
|
||||
ty: place_ty,
|
||||
ty,
|
||||
place: &place_desc,
|
||||
span,
|
||||
});
|
||||
if let Some(path) = path {
|
||||
err.subdiagnostic(crate::session_diagnostics::LongTypePath {
|
||||
path: path.display().to_string(),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
binds_to.sort();
|
||||
binds_to.dedup();
|
||||
|
@ -628,12 +635,19 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
self.suggest_cloning(err, place_ty, expr, Some(use_spans));
|
||||
}
|
||||
|
||||
let mut path = None;
|
||||
let ty = self.infcx.tcx.short_ty_string(place_ty, &mut path);
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
|
||||
is_partial_move: false,
|
||||
ty: place_ty,
|
||||
ty,
|
||||
place: &place_desc,
|
||||
span: use_span,
|
||||
});
|
||||
if let Some(path) = path {
|
||||
err.subdiagnostic(crate::session_diagnostics::LongTypePath {
|
||||
path: path.display().to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
use_spans.args_subdiag(err, |args_span| {
|
||||
crate::session_diagnostics::CaptureArgLabel::MoveOutPlace {
|
||||
|
@ -831,12 +845,19 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
|
|||
self.suggest_cloning(err, bind_to.ty, expr, None);
|
||||
}
|
||||
|
||||
let mut path = None;
|
||||
let ty = self.infcx.tcx.short_ty_string(bind_to.ty, &mut path);
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
|
||||
is_partial_move: false,
|
||||
ty: bind_to.ty,
|
||||
ty,
|
||||
place: place_desc,
|
||||
span: binding_span,
|
||||
});
|
||||
if let Some(path) = path {
|
||||
err.subdiagnostic(crate::session_diagnostics::LongTypePath {
|
||||
path: path.display().to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -459,17 +459,24 @@ pub(crate) enum OnClosureNote<'a> {
|
|||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum TypeNoCopy<'a, 'tcx> {
|
||||
#[note(borrowck_long_type_full_path)]
|
||||
#[note(borrowck_long_type_consider_verbose)]
|
||||
pub(crate) struct LongTypePath {
|
||||
pub(crate) path: String,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum TypeNoCopy<'a> {
|
||||
#[label(borrowck_ty_no_impl_copy)]
|
||||
Label {
|
||||
is_partial_move: bool,
|
||||
ty: Ty<'tcx>,
|
||||
ty: String,
|
||||
place: &'a str,
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
},
|
||||
#[note(borrowck_ty_no_impl_copy)]
|
||||
Note { is_partial_move: bool, ty: Ty<'tcx>, place: &'a str },
|
||||
Note { is_partial_move: bool, ty: String, place: &'a str },
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
|
@ -3,12 +3,10 @@ A type parameter which references `Self` in its default value was not specified.
|
|||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0393
|
||||
trait A<T=Self> {}
|
||||
trait A<T = Self> {}
|
||||
|
||||
fn together_we_will_rule_the_galaxy(son: &A) {}
|
||||
// error: the type parameter `T` must be explicitly specified in an
|
||||
// object type because its default value `Self` references the
|
||||
// type `Self`
|
||||
fn together_we_will_rule_the_galaxy(son: &dyn A) {}
|
||||
// error: the type parameter `T` must be explicitly specified
|
||||
```
|
||||
|
||||
A trait object is defined over a single, fully-defined trait. With a regular
|
||||
|
@ -23,7 +21,7 @@ disallowed. Making the trait concrete by explicitly specifying the value of the
|
|||
defaulted parameter will fix this issue. Fixed example:
|
||||
|
||||
```
|
||||
trait A<T=Self> {}
|
||||
trait A<T = Self> {}
|
||||
|
||||
fn together_we_will_rule_the_galaxy(son: &A<i32>) {} // Ok!
|
||||
fn together_we_will_rule_the_galaxy(son: &dyn A<i32>) {} // Ok!
|
||||
```
|
||||
|
|
|
@ -353,7 +353,13 @@ hir_analysis_missing_type_params =
|
|||
[one] reference
|
||||
*[other] references
|
||||
} to {$parameters}
|
||||
.note = because of the default `Self` reference, type parameters must be specified on object types
|
||||
.note = because the parameter {$parameterCount ->
|
||||
[one] default references
|
||||
*[other] defaults reference
|
||||
} `Self`, the {$parameterCount ->
|
||||
[one] parameter
|
||||
*[other] parameters
|
||||
} must be specified on the object type
|
||||
|
||||
hir_analysis_multiple_relaxed_default_bounds =
|
||||
type parameter has more than one relaxed default bound, only one is supported
|
||||
|
|
|
@ -237,16 +237,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
// Skip `Self`
|
||||
.skip(1)
|
||||
.map(|(index, arg)| {
|
||||
if arg == dummy_self.into() {
|
||||
if arg.walk().any(|arg| arg == dummy_self.into()) {
|
||||
let param = &generics.own_params[index];
|
||||
missing_type_params.push(param.name);
|
||||
Ty::new_misc_error(tcx).into()
|
||||
} else if arg.walk().any(|arg| arg == dummy_self.into()) {
|
||||
let guar = self.dcx().span_delayed_bug(
|
||||
span,
|
||||
"trait object trait bounds reference `Self`",
|
||||
);
|
||||
replace_dummy_self_with_error(tcx, arg, guar)
|
||||
} else {
|
||||
arg
|
||||
}
|
||||
|
|
|
@ -185,6 +185,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
rhs_ty: Ty<'tcx>,
|
||||
can_satisfy: impl FnOnce(Ty<'tcx>, Ty<'tcx>) -> bool,
|
||||
) -> bool {
|
||||
if lhs_expr.span.in_derive_expansion() || rhs_expr.span.in_derive_expansion() {
|
||||
return false;
|
||||
}
|
||||
let Some((_, lhs_output_ty, lhs_inputs)) = self.extract_callable_info(lhs_ty) else {
|
||||
return false;
|
||||
};
|
||||
|
|
|
@ -25,6 +25,8 @@ mir_build_borrow_of_moved_value = borrow of moved value
|
|||
.occurs_because_label = move occurs because `{$name}` has type `{$ty}`, which does not implement the `Copy` trait
|
||||
.value_borrowed_label = value borrowed here after move
|
||||
.suggestion = borrow this binding in the pattern to avoid moving the value
|
||||
.full_type_name = the full type name has been written to '{$path}'
|
||||
.consider_verbose = consider using `--verbose` to print the full type name to the console
|
||||
|
||||
mir_build_call_to_deprecated_safe_fn_requires_unsafe =
|
||||
call to deprecated safe function `{$function}` is unsafe and requires unsafe block
|
||||
|
|
|
@ -790,7 +790,7 @@ pub(crate) struct IrrefutableLetPatternsWhileLet {
|
|||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(mir_build_borrow_of_moved_value)]
|
||||
pub(crate) struct BorrowOfMovedValue<'tcx> {
|
||||
pub(crate) struct BorrowOfMovedValue {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
#[label(mir_build_occurs_because_label)]
|
||||
|
@ -798,9 +798,13 @@ pub(crate) struct BorrowOfMovedValue<'tcx> {
|
|||
#[label(mir_build_value_borrowed_label)]
|
||||
pub(crate) conflicts_ref: Vec<Span>,
|
||||
pub(crate) name: Symbol,
|
||||
pub(crate) ty: Ty<'tcx>,
|
||||
pub(crate) ty: String,
|
||||
#[suggestion(code = "ref ", applicability = "machine-applicable")]
|
||||
pub(crate) suggest_borrowing: Option<Span>,
|
||||
#[note(mir_build_full_type_name)]
|
||||
#[note(mir_build_consider_verbose)]
|
||||
pub(crate) has_path: bool,
|
||||
pub(crate) path: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
|
@ -795,12 +795,16 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat:
|
|||
}
|
||||
});
|
||||
if !conflicts_ref.is_empty() {
|
||||
let mut path = None;
|
||||
let ty = cx.tcx.short_ty_string(ty, &mut path);
|
||||
sess.dcx().emit_err(BorrowOfMovedValue {
|
||||
binding_span: pat.span,
|
||||
conflicts_ref,
|
||||
name,
|
||||
ty,
|
||||
suggest_borrowing: Some(pat.span.shrink_to_lo()),
|
||||
has_path: path.is_some(),
|
||||
path: path.map(|p| p.display().to_string()).unwrap_or_default(),
|
||||
});
|
||||
}
|
||||
return;
|
||||
|
|
|
@ -288,7 +288,7 @@ pub enum DebugAsHex {
|
|||
///
|
||||
/// `FormattingOptions` is a [`Formatter`] without an attached [`Write`] trait.
|
||||
/// It is mainly used to construct `Formatter` instances.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[unstable(feature = "formatting_options", issue = "118117")]
|
||||
pub struct FormattingOptions {
|
||||
flags: u32,
|
||||
|
@ -508,6 +508,15 @@ impl FormattingOptions {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "formatting_options", issue = "118117")]
|
||||
impl Default for FormattingOptions {
|
||||
/// Same as [`FormattingOptions::new()`].
|
||||
fn default() -> Self {
|
||||
// The `#[derive(Default)]` implementation would set `fill` to `\0` instead of space.
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration for formatting.
|
||||
///
|
||||
/// A `Formatter` represents various options related to formatting. Users do not
|
||||
|
|
|
@ -51,6 +51,12 @@ fn test_maybe_uninit_short() {
|
|||
assert_eq!(format!("{x:?}"), "MaybeUninit<u32>");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn formatting_options_ctor() {
|
||||
use core::fmt::FormattingOptions;
|
||||
assert_eq!(FormattingOptions::new(), FormattingOptions::default());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn formatting_options_flags() {
|
||||
use core::fmt::*;
|
||||
|
|
|
@ -130,7 +130,12 @@ impl Thread {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"))]
|
||||
#[cfg(any(
|
||||
target_os = "linux",
|
||||
target_os = "freebsd",
|
||||
target_os = "dragonfly",
|
||||
target_os = "nuttx"
|
||||
))]
|
||||
pub fn set_name(name: &CStr) {
|
||||
unsafe {
|
||||
cfg_if::cfg_if! {
|
||||
|
@ -139,7 +144,7 @@ impl Thread {
|
|||
const TASK_COMM_LEN: usize = 16;
|
||||
let name = truncate_cstr::<{ TASK_COMM_LEN }>(name);
|
||||
} else {
|
||||
// FreeBSD and DragonFly BSD do not enforce length limits.
|
||||
// FreeBSD, DragonFly, FreeBSD and NuttX do not enforce length limits.
|
||||
}
|
||||
};
|
||||
// Available since glibc 2.12, musl 1.1.16, and uClibc 1.0.20 for Linux,
|
||||
|
@ -150,7 +155,7 @@ impl Thread {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "openbsd", target_os = "nuttx"))]
|
||||
#[cfg(target_os = "openbsd")]
|
||||
pub fn set_name(name: &CStr) {
|
||||
unsafe {
|
||||
libc::pthread_set_name_np(libc::pthread_self(), name.as_ptr());
|
||||
|
|
|
@ -1310,9 +1310,6 @@ def bootstrap(args):
|
|||
args = [build.bootstrap_binary()]
|
||||
args.extend(sys.argv[1:])
|
||||
env = os.environ.copy()
|
||||
# The Python process ID is used when creating a Windows job object
|
||||
# (see src\bootstrap\src\utils\job.rs)
|
||||
env["BOOTSTRAP_PARENT_ID"] = str(os.getpid())
|
||||
env["BOOTSTRAP_PYTHON"] = sys.executable
|
||||
run(args, env=env, verbose=build.verbose, is_bootstrap=True)
|
||||
|
||||
|
|
|
@ -57,7 +57,9 @@ fn main() {
|
|||
}
|
||||
err => {
|
||||
drop(err);
|
||||
if let Ok(pid) = pid {
|
||||
// #135972: We can reach this point when the lock has been taken,
|
||||
// but the locker has not yet written its PID to the file
|
||||
if let Some(pid) = pid.ok().filter(|pid| !pid.is_empty()) {
|
||||
println!("WARNING: build directory locked by process {pid}, waiting for lock");
|
||||
} else {
|
||||
println!("WARNING: build directory locked, waiting for lock");
|
||||
|
|
|
@ -42,9 +42,9 @@ pub unsafe fn setup(build: &mut crate::Build) {
|
|||
#[cfg(windows)]
|
||||
mod for_windows {
|
||||
use std::ffi::c_void;
|
||||
use std::{env, io, mem};
|
||||
use std::{io, mem};
|
||||
|
||||
use windows::Win32::Foundation::{CloseHandle, DUPLICATE_SAME_ACCESS, DuplicateHandle, HANDLE};
|
||||
use windows::Win32::Foundation::CloseHandle;
|
||||
use windows::Win32::System::Diagnostics::Debug::{
|
||||
SEM_NOGPFAULTERRORBOX, SetErrorMode, THREAD_ERROR_MODE,
|
||||
};
|
||||
|
@ -53,9 +53,7 @@ mod for_windows {
|
|||
JOB_OBJECT_LIMIT_PRIORITY_CLASS, JOBOBJECT_EXTENDED_LIMIT_INFORMATION,
|
||||
JobObjectExtendedLimitInformation, SetInformationJobObject,
|
||||
};
|
||||
use windows::Win32::System::Threading::{
|
||||
BELOW_NORMAL_PRIORITY_CLASS, GetCurrentProcess, OpenProcess, PROCESS_DUP_HANDLE,
|
||||
};
|
||||
use windows::Win32::System::Threading::{BELOW_NORMAL_PRIORITY_CLASS, GetCurrentProcess};
|
||||
use windows::core::PCWSTR;
|
||||
|
||||
use crate::Build;
|
||||
|
@ -95,49 +93,8 @@ mod for_windows {
|
|||
return;
|
||||
}
|
||||
|
||||
// If we've got a parent process (e.g., the python script that called us)
|
||||
// then move ownership of this job object up to them. That way if the python
|
||||
// script is killed (e.g., via ctrl-c) then we'll all be torn down.
|
||||
//
|
||||
// If we don't have a parent (e.g., this was run directly) then we
|
||||
// intentionally leak the job object handle. When our process exits
|
||||
// Note: we intentionally leak the job object handle. When our process exits
|
||||
// (normally or abnormally) it will close the handle implicitly, causing all
|
||||
// processes in the job to be cleaned up.
|
||||
let pid = match env::var("BOOTSTRAP_PARENT_ID") {
|
||||
Ok(s) => s,
|
||||
Err(..) => return,
|
||||
};
|
||||
|
||||
let parent = match OpenProcess(PROCESS_DUP_HANDLE, false, pid.parse().unwrap()).ok() {
|
||||
Some(parent) => parent,
|
||||
_ => {
|
||||
// If we get a null parent pointer here, it is possible that either
|
||||
// we have an invalid pid or the parent process has been closed.
|
||||
// Since the first case rarely happens
|
||||
// (only when wrongly setting the environmental variable),
|
||||
// it might be better to improve the experience of the second case
|
||||
// when users have interrupted the parent process and we haven't finish
|
||||
// duplicating the handle yet.
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let mut parent_handle = HANDLE::default();
|
||||
// If this fails, well at least we tried! An example of DuplicateHandle
|
||||
// failing in the past has been when the wrong python2 package spawned this
|
||||
// build system (e.g., the `python2` package in MSYS instead of
|
||||
// `mingw-w64-x86_64-python2`). Not sure why it failed, but the "failure
|
||||
// mode" here is that we only clean everything up when the build system
|
||||
// dies, not when the python parent does, so not too bad.
|
||||
let _ = DuplicateHandle(
|
||||
GetCurrentProcess(),
|
||||
job,
|
||||
parent,
|
||||
&mut parent_handle,
|
||||
0,
|
||||
false,
|
||||
DUPLICATE_SAME_ACCESS,
|
||||
);
|
||||
CloseHandle(parent).ok();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ pub struct JsonInvocation {
|
|||
//
|
||||
// This is necessary to easily correlate this invocation with logs or other data.
|
||||
pub start_time: u64,
|
||||
#[serde(deserialize_with = "null_as_f64_nan")]
|
||||
pub duration_including_children_sec: f64,
|
||||
pub children: Vec<JsonNode>,
|
||||
}
|
||||
|
@ -28,6 +29,7 @@ pub enum JsonNode {
|
|||
type_: String,
|
||||
debug_repr: String,
|
||||
|
||||
#[serde(deserialize_with = "null_as_f64_nan")]
|
||||
duration_excluding_children_sec: f64,
|
||||
system_stats: JsonStepSystemStats,
|
||||
|
||||
|
@ -88,5 +90,11 @@ pub struct JsonInvocationSystemStats {
|
|||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub struct JsonStepSystemStats {
|
||||
#[serde(deserialize_with = "null_as_f64_nan")]
|
||||
pub cpu_utilization_percent: f64,
|
||||
}
|
||||
|
||||
fn null_as_f64_nan<'de, D: serde::Deserializer<'de>>(d: D) -> Result<f64, D::Error> {
|
||||
use serde::Deserialize as _;
|
||||
Option::<f64>::deserialize(d).map(|f| f.unwrap_or(f64::NAN))
|
||||
}
|
||||
|
|
|
@ -409,7 +409,6 @@ ui/closure_context/issue-26046-fn-once.rs
|
|||
ui/closure_context/issue-42065.rs
|
||||
ui/closures/2229_closure_analysis/issue-118144.rs
|
||||
ui/closures/2229_closure_analysis/issue-87378.rs
|
||||
ui/closures/2229_closure_analysis/issue-87987.rs
|
||||
ui/closures/2229_closure_analysis/issue-88118-2.rs
|
||||
ui/closures/2229_closure_analysis/issue-88476.rs
|
||||
ui/closures/2229_closure_analysis/issue-89606.rs
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
//@ run-pass
|
||||
//@ edition:2021
|
||||
|
||||
struct Props {
|
||||
field_1: u32, //~ WARNING: fields `field_1` and `field_2` are never read
|
||||
field_2: u32,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Test 1
|
||||
let props_2 = Props { field_1: 1, field_2: 1 };
|
||||
|
||||
let _ = || {
|
||||
let _: Props = props_2;
|
||||
};
|
||||
|
||||
// Test 2
|
||||
let mut arr = [1, 3, 4, 5];
|
||||
|
||||
let mref = &mut arr;
|
||||
|
||||
let _c = || match arr {
|
||||
[_, _, _, _] => println!("A"),
|
||||
};
|
||||
|
||||
println!("{:#?}", mref);
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
warning: fields `field_1` and `field_2` are never read
|
||||
--> $DIR/issue-87987.rs:5:5
|
||||
|
|
||||
LL | struct Props {
|
||||
| ----- fields in this struct
|
||||
LL | field_1: u32,
|
||||
| ^^^^^^^
|
||||
LL | field_2: u32,
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: `#[warn(dead_code)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
//! When a closure syntactically captures a place, but doesn't actually capture
|
||||
//! it, make sure MIR building doesn't ICE when handling that place.
|
||||
//!
|
||||
//! Under the Rust 2021 disjoint capture rules, this sort of non-capture can
|
||||
//! occur when a place is only inspected by infallible non-binding patterns.
|
||||
|
||||
// FIXME(#135985): On its own, this test should probably just be check-pass.
|
||||
// But there are few/no other tests that use non-binding array patterns and
|
||||
// invoke the later parts of the compiler, so building/running has some value.
|
||||
|
||||
//@ run-pass
|
||||
//@ edition:2021
|
||||
|
||||
#[expect(dead_code)]
|
||||
struct Props {
|
||||
field_1: u32,
|
||||
field_2: u32,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Test 1
|
||||
let props_2 = Props { field_1: 1, field_2: 1 };
|
||||
|
||||
let _ = || {
|
||||
let _: Props = props_2;
|
||||
};
|
||||
|
||||
// Test 2
|
||||
let mut arr = [1, 3, 4, 5];
|
||||
|
||||
let mref = &mut arr;
|
||||
|
||||
// These array patterns don't need to inspect the array, so the array
|
||||
// isn't captured.
|
||||
let _c = || match arr {
|
||||
[_, _, _, _] => println!("C"),
|
||||
};
|
||||
let _d = || match arr {
|
||||
[_, .., _] => println!("D"),
|
||||
};
|
||||
let _e = || match arr {
|
||||
[_, ..] => println!("E"),
|
||||
};
|
||||
|
||||
println!("{:#?}", mref);
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
#[derive(PartialEq)] //~ NOTE in this expansion
|
||||
pub struct Function {
|
||||
callback: Rc<dyn Fn()>, //~ ERROR binary operation `==` cannot be applied to type `Rc<dyn Fn()>`
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,14 @@
|
|||
error[E0369]: binary operation `==` cannot be applied to type `Rc<dyn Fn()>`
|
||||
--> $DIR/do-not-suggest-calling-fn-in-derive-macro.rs:5:5
|
||||
|
|
||||
LL | #[derive(PartialEq)]
|
||||
| --------- in this derive macro expansion
|
||||
LL | pub struct Function {
|
||||
LL | callback: Rc<dyn Fn()>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this error originates in the derive macro `PartialEq` (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 E0369`.
|
17
tests/ui/diagnostic-width/non-copy-type-moved.rs
Normal file
17
tests/ui/diagnostic-width/non-copy-type-moved.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
//@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes
|
||||
//@ normalize-stderr: "long-type-\d+" -> "long-type-hash"
|
||||
type A = (String, String, String, String);
|
||||
type B = (A, A, A, A);
|
||||
type C = (B, B, B, B);
|
||||
type D = (C, C, C, C);
|
||||
|
||||
trait Trait {}
|
||||
|
||||
fn require_trait<T: Trait>() {}
|
||||
|
||||
fn foo(x: D) {
|
||||
let _a = x;
|
||||
let _b = x; //~ ERROR use of moved value
|
||||
}
|
||||
|
||||
fn main() {}
|
20
tests/ui/diagnostic-width/non-copy-type-moved.stderr
Normal file
20
tests/ui/diagnostic-width/non-copy-type-moved.stderr
Normal file
|
@ -0,0 +1,20 @@
|
|||
error[E0382]: use of moved value: `x`
|
||||
--> $DIR/non-copy-type-moved.rs:14:14
|
||||
|
|
||||
LL | fn foo(x: D) {
|
||||
| - move occurs because `x` has type `((..., ..., ..., ...), ..., ..., ...)`, which does not implement the `Copy` trait
|
||||
LL | let _a = x;
|
||||
| - value moved here
|
||||
LL | let _b = x;
|
||||
| ^ value used here after move
|
||||
|
|
||||
= note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/non-copy-type-moved/non-copy-type-moved.long-type-hash.txt'
|
||||
= note: consider using `--verbose` to print the full type name to the console
|
||||
help: consider cloning the value if the performance cost is acceptable
|
||||
|
|
||||
LL | let _a = x.clone();
|
||||
| ++++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0382`.
|
17
tests/ui/dyn-compatibility/default-param-self-projection.rs
Normal file
17
tests/ui/dyn-compatibility/default-param-self-projection.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
trait A<C = <Self as D>::E> {}
|
||||
|
||||
trait D {
|
||||
type E;
|
||||
}
|
||||
|
||||
impl A<()> for () {}
|
||||
impl D for () {
|
||||
type E = ();
|
||||
}
|
||||
|
||||
fn f() {
|
||||
let B: &dyn A = &();
|
||||
//~^ ERROR the type parameter `C` must be explicitly specified
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,18 @@
|
|||
error[E0393]: the type parameter `C` must be explicitly specified
|
||||
--> $DIR/default-param-self-projection.rs:13:17
|
||||
|
|
||||
LL | trait A<C = <Self as D>::E> {}
|
||||
| --------------------------- type parameter `C` must be specified for this
|
||||
...
|
||||
LL | let B: &dyn A = &();
|
||||
| ^
|
||||
|
|
||||
= note: because the parameter default references `Self`, the parameter must be specified on the object type
|
||||
help: set the type parameter to the desired type
|
||||
|
|
||||
LL | let B: &dyn A<C> = &();
|
||||
| +++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0393`.
|
|
@ -7,7 +7,7 @@ LL |
|
|||
LL | fn together_we_will_rule_the_galaxy(son: &dyn A) {}
|
||||
| ^
|
||||
|
|
||||
= note: because of the default `Self` reference, type parameters must be specified on object types
|
||||
= note: because the parameter default references `Self`, the parameter must be specified on the object type
|
||||
help: set the type parameter to the desired type
|
||||
|
|
||||
LL | fn together_we_will_rule_the_galaxy(son: &dyn A<T>) {}
|
||||
|
|
|
@ -7,7 +7,7 @@ LL |
|
|||
LL | fn f(a: &dyn A) {}
|
||||
| ^
|
||||
|
|
||||
= note: because of the default `Self` reference, type parameters must be specified on object types
|
||||
= note: because the parameter default references `Self`, the parameter must be specified on the object type
|
||||
help: set the type parameter to the desired type
|
||||
|
|
||||
LL | fn f(a: &dyn A<T>) {}
|
||||
|
|
|
@ -10,6 +10,7 @@ fn w<'a, T: 'a, F: Fn(&'a T)>() {
|
|||
let b: &dyn FromResidual = &();
|
||||
//~^ ERROR: the trait `FromResidual` is not dyn compatible
|
||||
//~| ERROR: the trait `FromResidual` is not dyn compatible
|
||||
//~| ERROR the type parameter `R` must be explicitly specified
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
error[E0393]: the type parameter `R` must be explicitly specified
|
||||
--> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:17
|
||||
|
|
||||
LL | trait FromResidual<R = <Self as Try>::Residual> {
|
||||
| ----------------------------------------------- type parameter `R` must be specified for this
|
||||
...
|
||||
LL | let b: &dyn FromResidual = &();
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
= note: because the parameter default references `Self`, the parameter must be specified on the object type
|
||||
help: set the type parameter to the desired type
|
||||
|
|
||||
LL | let b: &dyn FromResidual<R> = &();
|
||||
| +++
|
||||
|
||||
error[E0038]: the trait `FromResidual` is not dyn compatible
|
||||
--> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:32
|
||||
|
|
||||
|
@ -45,6 +60,7 @@ help: alternatively, consider constraining `from_residual` so it does not apply
|
|||
LL | fn from_residual(residual: R) -> Self where Self: Sized;
|
||||
| +++++++++++++++++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0038`.
|
||||
Some errors have detailed explanations: E0038, E0393.
|
||||
For more information about an error, try `rustc --explain E0038`.
|
||||
|
|
|
@ -97,7 +97,7 @@ LL | pub trait Bar<X=usize, A=Self> {
|
|||
LL | let e = Bar::<usize>::lol();
|
||||
| ^^^^^^^^^^^^ missing reference to `A`
|
||||
|
|
||||
= note: because of the default `Self` reference, type parameters must be specified on object types
|
||||
= note: because the parameter default references `Self`, the parameter must be specified on the object type
|
||||
|
||||
error: aborting due to 5 previous errors; 5 warnings emitted
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ LL | trait Foo<T=Self> {
|
|||
LL | fn foo(x: &dyn Foo) { }
|
||||
| ^^^
|
||||
|
|
||||
= note: because of the default `Self` reference, type parameters must be specified on object types
|
||||
= note: because the parameter default references `Self`, the parameter must be specified on the object type
|
||||
help: set the type parameter to the desired type
|
||||
|
|
||||
LL | fn foo(x: &dyn Foo<T>) { }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue