Auto merge of #105892 - Dylan-DPC:rollup-eozolx4, r=Dylan-DPC
Rollup of 5 pull requests Successful merges: - #105682 (Use `expose_addr()` in `fmt::Pointer`) - #105839 (Suggest a `T: Send` bound for `&mut T` upvars in `Send` generators) - #105864 (clippy::complexity fixes) - #105882 (Don't ICE in closure arg borrow suggestion) - #105889 (Fix `uninlined_format_args` in libtest) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
4653c93e44
|
@ -600,7 +600,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
self.impl_trait_defs = current_impl_trait_defs;
|
||||
self.impl_trait_bounds = current_impl_trait_bounds;
|
||||
|
||||
debug_assert!(self.children.iter().find(|(id, _)| id == &def_id).is_none());
|
||||
debug_assert!(!self.children.iter().any(|(id, _)| id == &def_id));
|
||||
self.children.push((def_id, hir::MaybeOwner::Owner(info)));
|
||||
}
|
||||
|
||||
|
|
|
@ -2059,12 +2059,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||
) -> Option<InitIndex> {
|
||||
let mpi = self.move_data.rev_lookup.find_local(local);
|
||||
let ii = &self.move_data.init_path_map[mpi];
|
||||
for &index in ii {
|
||||
if flow_state.ever_inits.contains(index) {
|
||||
return Some(index);
|
||||
}
|
||||
}
|
||||
None
|
||||
ii.into_iter().find(|&&index| flow_state.ever_inits.contains(index)).copied()
|
||||
}
|
||||
|
||||
/// Adds the place into the used mutable variables set
|
||||
|
|
|
@ -233,8 +233,8 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
// Set KCFI operand bundle
|
||||
let is_indirect_call = unsafe { llvm::LLVMIsAFunction(llfn).is_none() };
|
||||
let kcfi_bundle =
|
||||
if self.tcx.sess.is_sanitizer_kcfi_enabled() && fn_abi.is_some() && is_indirect_call {
|
||||
let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi.unwrap());
|
||||
if self.tcx.sess.is_sanitizer_kcfi_enabled() && let Some(fn_abi) = fn_abi && is_indirect_call {
|
||||
let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi);
|
||||
Some(llvm::OperandBundleDef::new("kcfi", &[self.const_u32(kcfi_typeid)]))
|
||||
} else {
|
||||
None
|
||||
|
|
|
@ -123,7 +123,7 @@ fn try_filter_fat_archs<'a>(
|
|||
) -> io::Result<Option<(&'a [u8], u64)>> {
|
||||
let archs = archs.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
||||
|
||||
let desired = match archs.iter().filter(|a| a.architecture() == target_arch).next() {
|
||||
let desired = match archs.iter().find(|a| a.architecture() == target_arch) {
|
||||
Some(a) => a,
|
||||
None => return Ok(None),
|
||||
};
|
||||
|
|
|
@ -1124,9 +1124,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
let hir = self.tcx.hir();
|
||||
let cond_parent = hir.parent_iter(expr.hir_id).skip_while(|(_, node)| {
|
||||
matches!(node, hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Binary(op, _, _), .. }) if op.node == hir::BinOpKind::And)
|
||||
}).next();
|
||||
let cond_parent = hir.parent_iter(expr.hir_id).find(|(_, node)| {
|
||||
!matches!(node, hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Binary(op, _, _), .. }) if op.node == hir::BinOpKind::And)
|
||||
});
|
||||
// Don't suggest:
|
||||
// `let Some(_) = a.is_some() && b`
|
||||
// ++++++++++
|
||||
|
|
|
@ -488,7 +488,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
|
|||
// If this empty region is from a universe that can
|
||||
// name the placeholder, then the placeholder is
|
||||
// larger; otherwise, the only ancestor is `'static`.
|
||||
if a_ui.can_name(placeholder.universe) { true } else { false }
|
||||
return a_ui.can_name(placeholder.universe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,18 +87,12 @@ impl<'tcx> Rollback<UndoLog<'tcx>> for InferCtxtInner<'tcx> {
|
|||
|
||||
/// The combined undo log for all the various unification tables. For each change to the storage
|
||||
/// for any kind of inference variable, we record an UndoLog entry in the vector here.
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Default)]
|
||||
pub(crate) struct InferCtxtUndoLogs<'tcx> {
|
||||
logs: Vec<UndoLog<'tcx>>,
|
||||
num_open_snapshots: usize,
|
||||
}
|
||||
|
||||
impl Default for InferCtxtUndoLogs<'_> {
|
||||
fn default() -> Self {
|
||||
Self { logs: Default::default(), num_open_snapshots: Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
/// The UndoLogs trait defines how we undo a particular kind of action (of type T). We can undo any
|
||||
/// action that is convertible into an UndoLog (per the From impls above).
|
||||
impl<'tcx, T> UndoLogs<T> for InferCtxtUndoLogs<'tcx>
|
||||
|
|
|
@ -103,12 +103,7 @@ impl EffectiveVisibilities {
|
|||
|
||||
pub fn public_at_level(&self, id: LocalDefId) -> Option<Level> {
|
||||
self.effective_vis(id).and_then(|effective_vis| {
|
||||
for level in Level::all_levels() {
|
||||
if effective_vis.is_public_at_level(level) {
|
||||
return Some(level);
|
||||
}
|
||||
}
|
||||
None
|
||||
Level::all_levels().into_iter().find(|&level| effective_vis.is_public_at_level(level))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -182,7 +182,7 @@ fn replace_flattened_locals<'tcx>(
|
|||
let mut fragments = IndexVec::new();
|
||||
for (k, v) in &replacements.fields {
|
||||
fragments.ensure_contains_elem(k.local, || Vec::new());
|
||||
fragments[k.local].push((&k.projection[..], *v));
|
||||
fragments[k.local].push((k.projection, *v));
|
||||
}
|
||||
debug!(?fragments);
|
||||
|
||||
|
|
|
@ -595,8 +595,8 @@ fn check_recursion_limit<'tcx>(
|
|||
let def_path_str = tcx.def_path_str(def_id);
|
||||
let (shrunk, written_to_path) = shrunk_instance_name(tcx, &instance);
|
||||
let mut path = PathBuf::new();
|
||||
let was_written = if written_to_path.is_some() {
|
||||
path = written_to_path.unwrap();
|
||||
let was_written = if let Some(written_to_path) = written_to_path {
|
||||
path = written_to_path;
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
|
|
|
@ -277,8 +277,7 @@ impl<'a> Parser<'a> {
|
|||
if let Some(arg) = args
|
||||
.iter()
|
||||
.rev()
|
||||
.skip_while(|arg| matches!(arg, AngleBracketedArg::Constraint(_)))
|
||||
.next()
|
||||
.find(|arg| !matches!(arg, AngleBracketedArg::Constraint(_)))
|
||||
{
|
||||
err.span_suggestion_verbose(
|
||||
arg.span().shrink_to_hi(),
|
||||
|
|
|
@ -787,7 +787,6 @@ impl<'tcx> DeadVisitor<'tcx> {
|
|||
let mut dead_codes = dead_codes
|
||||
.iter()
|
||||
.filter(|v| !v.name.as_str().starts_with('_'))
|
||||
.map(|v| v)
|
||||
.collect::<Vec<&DeadVariant>>();
|
||||
if dead_codes.is_empty() {
|
||||
return;
|
||||
|
|
|
@ -122,7 +122,7 @@ pub fn sysroot_candidates() -> SmallVec<[PathBuf; 2]> {
|
|||
let target = crate::config::host_triple();
|
||||
let mut sysroot_candidates: SmallVec<[PathBuf; 2]> =
|
||||
smallvec![get_or_default_sysroot().expect("Failed finding sysroot")];
|
||||
let path = current_dll_path().and_then(|s| Ok(s.canonicalize().map_err(|e| e.to_string())?));
|
||||
let path = current_dll_path().and_then(|s| s.canonicalize().map_err(|e| e.to_string()));
|
||||
if let Ok(dll) = path {
|
||||
// use `parent` twice to chop off the file name and then also the
|
||||
// directory containing the dll which should be either `lib` or `bin`.
|
||||
|
@ -165,7 +165,7 @@ pub fn get_or_default_sysroot() -> Result<PathBuf, String> {
|
|||
}
|
||||
|
||||
fn default_from_rustc_driver_dll() -> Result<PathBuf, String> {
|
||||
let dll = current_dll_path().and_then(|s| Ok(canonicalize(s)))?;
|
||||
let dll = current_dll_path().map(|s| canonicalize(s))?;
|
||||
|
||||
// `dll` will be in one of the following two:
|
||||
// - compiler's libdir: $sysroot/lib/*.dll
|
||||
|
|
|
@ -99,13 +99,8 @@ fn is_c_void_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
|
|||
ty::Adt(adt_def, ..) => {
|
||||
let def_id = adt_def.0.did;
|
||||
let crate_name = tcx.crate_name(def_id.krate);
|
||||
if tcx.item_name(def_id).as_str() == "c_void"
|
||||
tcx.item_name(def_id).as_str() == "c_void"
|
||||
&& (crate_name == sym::core || crate_name == sym::std || crate_name == sym::libc)
|
||||
{
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
|
@ -267,8 +262,7 @@ fn encode_predicates<'tcx>(
|
|||
) -> String {
|
||||
// <predicate1[..predicateN]>E as part of vendor extended type
|
||||
let mut s = String::new();
|
||||
let predicates: Vec<ty::PolyExistentialPredicate<'tcx>> =
|
||||
predicates.iter().map(|predicate| predicate).collect();
|
||||
let predicates: Vec<ty::PolyExistentialPredicate<'tcx>> = predicates.iter().collect();
|
||||
for predicate in predicates {
|
||||
s.push_str(&encode_predicate(tcx, predicate, dict, options));
|
||||
}
|
||||
|
@ -322,7 +316,7 @@ fn encode_substs<'tcx>(
|
|||
) -> String {
|
||||
// [I<subst1..substN>E] as part of vendor extended type
|
||||
let mut s = String::new();
|
||||
let substs: Vec<GenericArg<'_>> = substs.iter().map(|subst| subst).collect();
|
||||
let substs: Vec<GenericArg<'_>> = substs.iter().collect();
|
||||
if !substs.is_empty() {
|
||||
s.push('I');
|
||||
for subst in substs {
|
||||
|
@ -703,11 +697,8 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
|
|||
tcx.layout_of(param_env.and(ty)).map_or(false, |layout| layout.is_zst());
|
||||
!is_zst
|
||||
});
|
||||
if field.is_none() {
|
||||
// Transform repr(transparent) types without non-ZST field into ()
|
||||
ty = tcx.mk_unit();
|
||||
} else {
|
||||
let ty0 = tcx.type_of(field.unwrap().did);
|
||||
if let Some(field) = field {
|
||||
let ty0 = tcx.type_of(field.did);
|
||||
// Generalize any repr(transparent) user-defined type that is either a pointer
|
||||
// or reference, and either references itself or any other type that contains or
|
||||
// references itself, to avoid a reference cycle.
|
||||
|
@ -720,6 +711,9 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
|
|||
} else {
|
||||
ty = transform_ty(tcx, ty0, options);
|
||||
}
|
||||
} else {
|
||||
// Transform repr(transparent) types without non-ZST field into ()
|
||||
ty = tcx.mk_unit();
|
||||
}
|
||||
} else {
|
||||
ty = tcx.mk_adt(*adt_def, transform_substs(tcx, substs, options));
|
||||
|
|
|
@ -1789,7 +1789,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
self.note_conflicting_closure_bounds(cause, &mut err);
|
||||
|
||||
if let Some(found_node) = found_node {
|
||||
hint_missing_borrow(span, found_span, found, expected, found_node, &mut err);
|
||||
hint_missing_borrow(span, found, expected, found_node, &mut err);
|
||||
}
|
||||
|
||||
err
|
||||
|
@ -2344,28 +2344,33 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
GeneratorInteriorOrUpvar::Upvar(upvar_span) => {
|
||||
// `Some(ref_ty)` if `target_ty` is `&T` and `T` fails to impl `Sync`
|
||||
let refers_to_non_sync = match target_ty.kind() {
|
||||
ty::Ref(_, ref_ty, _) => match self.evaluate_obligation(&obligation) {
|
||||
Ok(eval) if !eval.may_apply() => Some(ref_ty),
|
||||
// `Some((ref_ty, is_mut))` if `target_ty` is `&T` or `&mut T` and fails to impl `Send`
|
||||
let non_send = match target_ty.kind() {
|
||||
ty::Ref(_, ref_ty, mutability) => match self.evaluate_obligation(&obligation) {
|
||||
Ok(eval) if !eval.may_apply() => Some((ref_ty, mutability.is_mut())),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let (span_label, span_note) = match refers_to_non_sync {
|
||||
// if `target_ty` is `&T` and `T` fails to impl `Sync`,
|
||||
// include suggestions to make `T: Sync` so that `&T: Send`
|
||||
Some(ref_ty) => (
|
||||
format!(
|
||||
"has type `{}` which {}, because `{}` is not `Sync`",
|
||||
target_ty, trait_explanation, ref_ty
|
||||
),
|
||||
format!(
|
||||
"captured value {} because `&` references cannot be sent unless their referent is `Sync`",
|
||||
trait_explanation
|
||||
),
|
||||
),
|
||||
let (span_label, span_note) = match non_send {
|
||||
// if `target_ty` is `&T` or `&mut T` and fails to impl `Send`,
|
||||
// include suggestions to make `T: Sync` so that `&T: Send`,
|
||||
// or to make `T: Send` so that `&mut T: Send`
|
||||
Some((ref_ty, is_mut)) => {
|
||||
let ref_ty_trait = if is_mut { "Send" } else { "Sync" };
|
||||
let ref_kind = if is_mut { "&mut" } else { "&" };
|
||||
(
|
||||
format!(
|
||||
"has type `{}` which {}, because `{}` is not `{}`",
|
||||
target_ty, trait_explanation, ref_ty, ref_ty_trait
|
||||
),
|
||||
format!(
|
||||
"captured value {} because `{}` references cannot be sent unless their referent is `{}`",
|
||||
trait_explanation, ref_kind, ref_ty_trait
|
||||
),
|
||||
)
|
||||
}
|
||||
None => (
|
||||
format!("has type `{}` which {}", target_ty, trait_explanation),
|
||||
format!("captured value {}", trait_explanation),
|
||||
|
@ -3455,7 +3460,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||
/// Add a hint to add a missing borrow or remove an unnecessary one.
|
||||
fn hint_missing_borrow<'tcx>(
|
||||
span: Span,
|
||||
found_span: Span,
|
||||
found: Ty<'tcx>,
|
||||
expected: Ty<'tcx>,
|
||||
found_node: Node<'_>,
|
||||
|
@ -3474,9 +3478,8 @@ fn hint_missing_borrow<'tcx>(
|
|||
}
|
||||
};
|
||||
|
||||
let fn_decl = found_node
|
||||
.fn_decl()
|
||||
.unwrap_or_else(|| span_bug!(found_span, "found node must be a function"));
|
||||
// This could be a variant constructor, for example.
|
||||
let Some(fn_decl) = found_node.fn_decl() else { return; };
|
||||
|
||||
let arg_spans = fn_decl.inputs.iter().map(|ty| ty.span);
|
||||
|
||||
|
|
|
@ -76,11 +76,7 @@ mod rustc {
|
|||
}
|
||||
};
|
||||
|
||||
let ret = if self.visibility(def_id).is_accessible_from(parent, *self) {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let ret: bool = self.visibility(def_id).is_accessible_from(parent, *self);
|
||||
|
||||
trace!(?ret, "ret");
|
||||
ret
|
||||
|
|
|
@ -2471,8 +2471,8 @@ impl Display for char {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Pointer for *const T {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||
// Cast is needed here because `.addr()` requires `T: Sized`.
|
||||
pointer_fmt_inner((*self as *const ()).addr(), f)
|
||||
// Cast is needed here because `.expose_addr()` requires `T: Sized`.
|
||||
pointer_fmt_inner((*self as *const ()).expose_addr(), f)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -354,8 +354,7 @@ fn get_shuffle_seed(matches: &getopts::Matches, allow_unstable: bool) -> OptPart
|
|||
Err(e) => {
|
||||
return Err(format!(
|
||||
"argument for --shuffle-seed must be a number \
|
||||
(error: {})",
|
||||
e
|
||||
(error: {e})"
|
||||
));
|
||||
}
|
||||
},
|
||||
|
@ -383,8 +382,7 @@ fn get_test_threads(matches: &getopts::Matches) -> OptPartRes<Option<usize>> {
|
|||
Err(e) => {
|
||||
return Err(format!(
|
||||
"argument for --test-threads must be a number > 0 \
|
||||
(error: {})",
|
||||
e
|
||||
(error: {e})"
|
||||
));
|
||||
}
|
||||
},
|
||||
|
@ -418,8 +416,7 @@ fn get_format(
|
|||
Some(v) => {
|
||||
return Err(format!(
|
||||
"argument for --format must be pretty, terse, json or junit (was \
|
||||
{})",
|
||||
v
|
||||
{v})"
|
||||
));
|
||||
}
|
||||
};
|
||||
|
@ -436,8 +433,7 @@ fn get_color_config(matches: &getopts::Matches) -> OptPartRes<ColorConfig> {
|
|||
Some(v) => {
|
||||
return Err(format!(
|
||||
"argument for --color must be auto, always, or never (was \
|
||||
{})",
|
||||
v
|
||||
{v})"
|
||||
));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -53,7 +53,7 @@ impl<T: Write> JsonFormatter<T> {
|
|||
self.write_message(&*format!(r#", "stdout": "{}""#, EscapedString(stdout)))?;
|
||||
}
|
||||
if let Some(extra) = extra {
|
||||
self.write_message(&*format!(r#", {}"#, extra))?;
|
||||
self.write_message(&*format!(r#", {extra}"#))?;
|
||||
}
|
||||
self.writeln_message(" }")
|
||||
}
|
||||
|
@ -62,13 +62,12 @@ impl<T: Write> JsonFormatter<T> {
|
|||
impl<T: Write> OutputFormatter for JsonFormatter<T> {
|
||||
fn write_run_start(&mut self, test_count: usize, shuffle_seed: Option<u64>) -> io::Result<()> {
|
||||
let shuffle_seed_json = if let Some(shuffle_seed) = shuffle_seed {
|
||||
format!(r#", "shuffle_seed": {}"#, shuffle_seed)
|
||||
format!(r#", "shuffle_seed": {shuffle_seed}"#)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
self.writeln_message(&*format!(
|
||||
r#"{{ "type": "suite", "event": "started", "test_count": {}{} }}"#,
|
||||
test_count, shuffle_seed_json
|
||||
r#"{{ "type": "suite", "event": "started", "test_count": {test_count}{shuffle_seed_json} }}"#
|
||||
))
|
||||
}
|
||||
|
||||
|
|
|
@ -38,5 +38,5 @@ pub(crate) fn write_stderr_delimiter(test_output: &mut Vec<u8>, test_name: &Test
|
|||
Some(_) => test_output.push(b'\n'),
|
||||
None => (),
|
||||
}
|
||||
writeln!(test_output, "---- {} stderr ----", test_name).unwrap();
|
||||
writeln!(test_output, "---- {test_name} stderr ----").unwrap();
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ impl<T: Write> PrettyFormatter<T> {
|
|||
|
||||
pub fn write_ignored(&mut self, message: Option<&'static str>) -> io::Result<()> {
|
||||
if let Some(message) = message {
|
||||
self.write_short_result(&format!("ignored, {}", message), term::color::YELLOW)
|
||||
self.write_short_result(&format!("ignored, {message}"), term::color::YELLOW)
|
||||
} else {
|
||||
self.write_short_result("ignored", term::color::YELLOW)
|
||||
}
|
||||
|
|
|
@ -213,8 +213,7 @@ pub fn assert_test_result<T: Termination>(result: T) -> Result<(), String> {
|
|||
} else {
|
||||
Err(format!(
|
||||
"the test returned a termination value with a non-zero status code \
|
||||
({}) which indicates a failure",
|
||||
code
|
||||
({code}) which indicates a failure"
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@ -750,7 +749,7 @@ fn spawn_test_subprocess(
|
|||
})() {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
write!(&mut test_output, "Unexpected error: {}", e).unwrap();
|
||||
write!(&mut test_output, "Unexpected error: {e}").unwrap();
|
||||
TrFailed
|
||||
}
|
||||
};
|
||||
|
|
|
@ -44,9 +44,8 @@ pub fn calc_result<'a>(
|
|||
} else if let Some(panic_str) = maybe_panic_str {
|
||||
TestResult::TrFailedMsg(format!(
|
||||
r#"panic did not contain expected string
|
||||
panic message: `{:?}`,
|
||||
expected substring: `{:?}`"#,
|
||||
panic_str, msg
|
||||
panic message: `{panic_str:?}`,
|
||||
expected substring: `{msg:?}`"#
|
||||
))
|
||||
} else {
|
||||
TestResult::TrFailedMsg(format!(
|
||||
|
|
|
@ -107,16 +107,14 @@ impl TimeThreshold {
|
|||
let durations_str = env::var(env_var_name).ok()?;
|
||||
let (warn_str, critical_str) = durations_str.split_once(',').unwrap_or_else(|| {
|
||||
panic!(
|
||||
"Duration variable {} expected to have 2 numbers separated by comma, but got {}",
|
||||
env_var_name, durations_str
|
||||
"Duration variable {env_var_name} expected to have 2 numbers separated by comma, but got {durations_str}"
|
||||
)
|
||||
});
|
||||
|
||||
let parse_u64 = |v| {
|
||||
u64::from_str(v).unwrap_or_else(|_| {
|
||||
panic!(
|
||||
"Duration value in variable {} is expected to be a number, but got {}",
|
||||
env_var_name, v
|
||||
"Duration value in variable {env_var_name} is expected to be a number, but got {v}"
|
||||
)
|
||||
})
|
||||
};
|
||||
|
|
31
src/test/ui/generator/ref-upvar-not-send.rs
Normal file
31
src/test/ui/generator/ref-upvar-not-send.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
// For `Send` generators, suggest a `T: Sync` requirement for `&T` upvars,
|
||||
// and suggest a `T: Send` requirement for `&mut T` upvars.
|
||||
|
||||
#![feature(generators)]
|
||||
|
||||
fn assert_send<T: Send>(_: T) {}
|
||||
//~^ NOTE required by a bound in `assert_send`
|
||||
//~| NOTE required by this bound in `assert_send`
|
||||
//~| NOTE required by a bound in `assert_send`
|
||||
//~| NOTE required by this bound in `assert_send`
|
||||
|
||||
fn main() {
|
||||
let x: &*mut () = &std::ptr::null_mut();
|
||||
let y: &mut *mut () = &mut std::ptr::null_mut();
|
||||
assert_send(move || {
|
||||
//~^ ERROR generator cannot be sent between threads safely
|
||||
//~| NOTE generator is not `Send`
|
||||
yield;
|
||||
let _x = x;
|
||||
});
|
||||
//~^^ NOTE captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
|
||||
//~| NOTE has type `&*mut ()` which is not `Send`, because `*mut ()` is not `Sync`
|
||||
assert_send(move || {
|
||||
//~^ ERROR generator cannot be sent between threads safely
|
||||
//~| NOTE generator is not `Send`
|
||||
yield;
|
||||
let _y = y;
|
||||
});
|
||||
//~^^ NOTE captured value is not `Send` because `&mut` references cannot be sent unless their referent is `Send`
|
||||
//~| NOTE has type `&mut *mut ()` which is not `Send`, because `*mut ()` is not `Send`
|
||||
}
|
50
src/test/ui/generator/ref-upvar-not-send.stderr
Normal file
50
src/test/ui/generator/ref-upvar-not-send.stderr
Normal file
|
@ -0,0 +1,50 @@
|
|||
error: generator cannot be sent between threads safely
|
||||
--> $DIR/ref-upvar-not-send.rs:15:17
|
||||
|
|
||||
LL | assert_send(move || {
|
||||
| _________________^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | yield;
|
||||
LL | | let _x = x;
|
||||
LL | | });
|
||||
| |_____^ generator is not `Send`
|
||||
|
|
||||
= help: the trait `Sync` is not implemented for `*mut ()`
|
||||
note: captured value is not `Send` because `&` references cannot be sent unless their referent is `Sync`
|
||||
--> $DIR/ref-upvar-not-send.rs:19:18
|
||||
|
|
||||
LL | let _x = x;
|
||||
| ^ has type `&*mut ()` which is not `Send`, because `*mut ()` is not `Sync`
|
||||
note: required by a bound in `assert_send`
|
||||
--> $DIR/ref-upvar-not-send.rs:6:19
|
||||
|
|
||||
LL | fn assert_send<T: Send>(_: T) {}
|
||||
| ^^^^ required by this bound in `assert_send`
|
||||
|
||||
error: generator cannot be sent between threads safely
|
||||
--> $DIR/ref-upvar-not-send.rs:23:17
|
||||
|
|
||||
LL | assert_send(move || {
|
||||
| _________________^
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | yield;
|
||||
LL | | let _y = y;
|
||||
LL | | });
|
||||
| |_____^ generator is not `Send`
|
||||
|
|
||||
= help: within `[generator@$DIR/ref-upvar-not-send.rs:23:17: 23:24]`, the trait `Send` is not implemented for `*mut ()`
|
||||
note: captured value is not `Send` because `&mut` references cannot be sent unless their referent is `Send`
|
||||
--> $DIR/ref-upvar-not-send.rs:27:18
|
||||
|
|
||||
LL | let _y = y;
|
||||
| ^ has type `&mut *mut ()` which is not `Send`, because `*mut ()` is not `Send`
|
||||
note: required by a bound in `assert_send`
|
||||
--> $DIR/ref-upvar-not-send.rs:6:19
|
||||
|
|
||||
LL | fn assert_send<T: Send>(_: T) {}
|
||||
| ^^^^ required by this bound in `assert_send`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
10
src/test/ui/suggestions/enum-variant-arg-mismatch.rs
Normal file
10
src/test/ui/suggestions/enum-variant-arg-mismatch.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
pub enum Sexpr<'a> {
|
||||
Ident(&'a str),
|
||||
}
|
||||
|
||||
fn map<'a, F: Fn(String) -> Sexpr<'a>>(f: F) {}
|
||||
|
||||
fn main() {
|
||||
map(Sexpr::Ident);
|
||||
//~^ ERROR type mismatch in function arguments
|
||||
}
|
22
src/test/ui/suggestions/enum-variant-arg-mismatch.stderr
Normal file
22
src/test/ui/suggestions/enum-variant-arg-mismatch.stderr
Normal file
|
@ -0,0 +1,22 @@
|
|||
error[E0631]: type mismatch in function arguments
|
||||
--> $DIR/enum-variant-arg-mismatch.rs:8:9
|
||||
|
|
||||
LL | Ident(&'a str),
|
||||
| ----- found signature defined here
|
||||
...
|
||||
LL | map(Sexpr::Ident);
|
||||
| --- ^^^^^^^^^^^^ expected due to this
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: expected function signature `fn(String) -> _`
|
||||
found function signature `fn(&str) -> _`
|
||||
note: required by a bound in `map`
|
||||
--> $DIR/enum-variant-arg-mismatch.rs:5:15
|
||||
|
|
||||
LL | fn map<'a, F: Fn(String) -> Sexpr<'a>>(f: F) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `map`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0631`.
|
Loading…
Reference in a new issue