Tweak short_ty_string to reduce number of files

When shortening types and writing them to disk, make `short_ty_string`
capable of reusing the same file, instead of writing a file per
shortened type.
This commit is contained in:
Esteban Küber 2023-11-27 20:25:45 +00:00
parent a90372c6e8
commit 9d846fcc11
14 changed files with 124 additions and 119 deletions

View file

@ -262,7 +262,8 @@ fn suggest_missing_writer(
rcvr_ty: Ty<'tcx>,
rcvr_expr: &hir::Expr<'tcx>,
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
let (ty_str, _ty_file) = self.tcx.short_ty_string(rcvr_ty);
let mut file = None;
let ty_str = self.tcx.short_ty_string(rcvr_ty, &mut file);
let mut err = struct_span_err!(
self.tcx.sess,
rcvr_expr.span,
@ -280,6 +281,9 @@ fn suggest_missing_writer(
"a writer is needed before this format string",
);
};
if let Some(file) = file {
err.note(format!("the full type name has been written to '{}'", file.display()));
}
err
}
@ -299,11 +303,15 @@ pub fn report_no_match_method_error(
let mode = no_match_data.mode;
let tcx = self.tcx;
let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
let ((mut ty_str, ty_file), short_ty_str) =
let mut ty_file = None;
let (mut ty_str, short_ty_str) =
if trait_missing_method && let ty::Dynamic(predicates, _, _) = rcvr_ty.kind() {
((predicates.to_string(), None), with_forced_trimmed_paths!(predicates.to_string()))
(predicates.to_string(), with_forced_trimmed_paths!(predicates.to_string()))
} else {
(tcx.short_ty_string(rcvr_ty), with_forced_trimmed_paths!(rcvr_ty.to_string()))
(
tcx.short_ty_string(rcvr_ty, &mut ty_file),
with_forced_trimmed_paths!(rcvr_ty.to_string()),
)
};
let is_method = mode == Mode::MethodCall;
let unsatisfied_predicates = &no_match_data.unsatisfied_predicates;

View file

@ -1743,7 +1743,7 @@ enum Mismatch<'a> {
}
}
if let Some((expected, found, exp_p, found_p)) = expected_found {
if let Some((expected, found, path)) = expected_found {
let (expected_label, found_label, exp_found) = match exp_found {
Mismatch::Variable(ef) => (
ef.expected.prefix_string(self.tcx),
@ -1869,8 +1869,7 @@ enum Similar<'tcx> {
}
TypeError::Sorts(values) => {
let extra = expected == found;
let sort_string = |ty: Ty<'tcx>, path: Option<PathBuf>| {
let mut s = match (extra, ty.kind()) {
let sort_string = |ty: Ty<'tcx>| match (extra, ty.kind()) {
(true, ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) => {
let sm = self.tcx.sess.source_map();
let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo());
@ -1896,14 +1895,6 @@ enum Similar<'tcx> {
(true, _) => format!(" ({})", ty.sort_string(self.tcx)),
(false, _) => "".to_string(),
};
if let Some(path) = path {
s.push_str(&format!(
"\nthe full type name has been written to '{}'",
path.display(),
));
}
s
};
if !(values.expected.is_simple_text(self.tcx)
&& values.found.is_simple_text(self.tcx))
|| (exp_found.is_some_and(|ef| {
@ -1933,9 +1924,15 @@ enum Similar<'tcx> {
expected,
&found_label,
found,
&sort_string(values.expected, exp_p),
&sort_string(values.found, found_p),
&sort_string(values.expected),
&sort_string(values.found),
);
if let Some(path) = path {
diag.note(format!(
"the full type name has been written to '{}'",
path.display(),
));
}
}
}
}
@ -2101,7 +2098,7 @@ pub fn type_error_additional_suggestions(
if let &(MatchExpressionArm(box MatchExpressionArmCause { source, .. })
| BlockTailExpression(.., source)) = code
&& let hir::MatchSource::TryDesugar(_) = source
&& let Some((expected_ty, found_ty, _, _)) = self.values_str(trace.values)
&& let Some((expected_ty, found_ty, _)) = self.values_str(trace.values)
{
suggestions.push(TypeErrorAdditionalDiags::TryCannotConvert {
found: found_ty.content(),
@ -2219,8 +2216,7 @@ fn suggest_wrap_to_build_a_tuple(
fn values_str(
&self,
values: ValuePairs<'tcx>,
) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
{
) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>)> {
match values {
infer::Regions(exp_found) => self.expected_found_str(exp_found),
infer::Terms(exp_found) => self.expected_found_str_term(exp_found),
@ -2233,7 +2229,7 @@ fn values_str(
found: exp_found.found.print_trait_sugared(),
};
match self.expected_found_str(pretty_exp_found) {
Some((expected, found, _, _)) if expected == found => {
Some((expected, found, _)) if expected == found => {
self.expected_found_str(exp_found)
}
ret => ret,
@ -2245,7 +2241,7 @@ fn values_str(
return None;
}
let (exp, fnd) = self.cmp_fn_sig(&exp_found.expected, &exp_found.found);
Some((exp, fnd, None, None))
Some((exp, fnd, None))
}
}
}
@ -2253,8 +2249,7 @@ fn values_str(
fn expected_found_str_term(
&self,
exp_found: ty::error::ExpectedFound<ty::Term<'tcx>>,
) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
{
) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>)> {
let exp_found = self.resolve_vars_if_possible(exp_found);
if exp_found.references_error() {
return None;
@ -2269,25 +2264,21 @@ fn expected_found_str_term(
let len = self.tcx.sess().diagnostic_width() + 40;
let exp_s = exp.content();
let fnd_s = fnd.content();
let mut exp_p = None;
let mut fnd_p = None;
let mut path = None;
if exp_s.len() > len {
let (exp_s, exp_path) = self.tcx.short_ty_string(expected);
let exp_s = self.tcx.short_ty_string(expected, &mut path);
exp = DiagnosticStyledString::highlighted(exp_s);
exp_p = exp_path;
}
if fnd_s.len() > len {
let (fnd_s, fnd_path) = self.tcx.short_ty_string(found);
let fnd_s = self.tcx.short_ty_string(found, &mut path);
fnd = DiagnosticStyledString::highlighted(fnd_s);
fnd_p = fnd_path;
}
(exp, fnd, exp_p, fnd_p)
(exp, fnd, path)
}
_ => (
DiagnosticStyledString::highlighted(exp_found.expected.to_string()),
DiagnosticStyledString::highlighted(exp_found.found.to_string()),
None,
None,
),
})
}
@ -2296,8 +2287,7 @@ fn expected_found_str_term(
fn expected_found_str<T: fmt::Display + TypeFoldable<TyCtxt<'tcx>>>(
&self,
exp_found: ty::error::ExpectedFound<T>,
) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
{
) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>)> {
let exp_found = self.resolve_vars_if_possible(exp_found);
if exp_found.references_error() {
return None;
@ -2307,7 +2297,6 @@ fn expected_found_str<T: fmt::Display + TypeFoldable<TyCtxt<'tcx>>>(
DiagnosticStyledString::highlighted(exp_found.expected.to_string()),
DiagnosticStyledString::highlighted(exp_found.found.to_string()),
None,
None,
))
}
@ -2591,8 +2580,8 @@ fn report_sub_sup_conflict(
if let infer::Subtype(ref sup_trace) = sup_origin
&& let infer::Subtype(ref sub_trace) = sub_origin
&& let Some((sup_expected, sup_found, _, _)) = self.values_str(sup_trace.values)
&& let Some((sub_expected, sub_found, _, _)) = self.values_str(sub_trace.values)
&& let Some((sup_expected, sup_found, _)) = self.values_str(sup_trace.values)
&& let Some((sub_expected, sub_found, _)) = self.values_str(sub_trace.values)
&& sub_expected == sup_expected
&& sub_found == sup_found
{

View file

@ -22,7 +22,7 @@ pub(super) fn note_region_origin(&self, err: &mut Diagnostic, origin: &Subregion
infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
span: trace.cause.span,
requirement: ObligationCauseAsDiagArg(trace.cause.clone()),
expected_found: self.values_str(trace.values).map(|(e, f, _, _)| (e, f)),
expected_found: self.values_str(trace.values).map(|(e, f, _)| (e, f)),
}
.add_to_diagnostic(err),
infer::Reborrow(span) => {

View file

@ -345,33 +345,35 @@ pub fn ty_string_with_limit(self, ty: Ty<'tcx>, length_limit: usize) -> String {
short
}
pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option<PathBuf>) {
pub fn short_ty_string(self, ty: Ty<'tcx>, path: &mut Option<PathBuf>) -> String {
let regular = FmtPrinter::print_string(self, hir::def::Namespace::TypeNS, |cx| {
cx.pretty_print_type(ty)
})
.expect("could not write to `String`");
if !self.sess.opts.unstable_opts.write_long_types_to_disk {
return (regular, None);
return regular;
}
let width = self.sess.diagnostic_width();
let length_limit = width.saturating_sub(30);
if regular.len() <= width {
return (regular, None);
return regular;
}
let short = self.ty_string_with_limit(ty, length_limit);
if regular == short {
return (regular, None);
return regular;
}
// Multiple types might be shortened in a single error, ensure we create a file for each.
// Ensure we create an unique file for the type passed in when we create a file.
let mut s = DefaultHasher::new();
ty.hash(&mut s);
let hash = s.finish();
let path = self.output_filenames(()).temp_path_ext(&format!("long-type-{hash}.txt"), None);
match std::fs::write(&path, &regular) {
Ok(_) => (short, Some(path)),
Err(_) => (regular, None),
*path = Some(path.take().unwrap_or_else(|| {
self.output_filenames(()).temp_path_ext(&format!("long-type-{hash}.txt"), None)
}));
match std::fs::write(path.as_ref().unwrap(), &format!("{regular}\n")) {
Ok(_) => short,
Err(_) => regular,
}
}
}

View file

@ -1387,14 +1387,21 @@ fn suggest_add_reference_to_arg(
err.message =
vec![(rustc_errors::DiagnosticMessage::from(msg), Style::NoStyle)];
}
let mut file = None;
err.span_label(
span,
format!(
"the trait `{}` is not implemented for `{}`",
old_pred.print_modifiers_and_trait_path(),
old_pred.self_ty().skip_binder(),
self.tcx.short_ty_string(old_pred.self_ty().skip_binder(), &mut file),
),
);
if let Some(file) = file {
err.note(format!(
"the full type name has been written to '{}'",
file.display()
));
}
if imm_ref_self_ty_satisfies_pred && mut_ref_self_ty_satisfies_pred {
err.span_suggestions(
@ -2916,22 +2923,17 @@ fn note_obligation_cause_code<T>(
}
}
ObligationCauseCode::Coercion { source, target } => {
let (source, source_file) =
self.tcx.short_ty_string(self.resolve_vars_if_possible(source));
let (target, target_file) =
self.tcx.short_ty_string(self.resolve_vars_if_possible(target));
let mut file = None;
let source =
self.tcx.short_ty_string(self.resolve_vars_if_possible(source), &mut file);
let target =
self.tcx.short_ty_string(self.resolve_vars_if_possible(target), &mut file);
err.note(with_forced_trimmed_paths!(format!(
"required for the cast from `{source}` to `{target}`",
)));
if let Some(file) = source_file {
if let Some(file) = file {
err.note(format!(
"the full name for the source type has been written to '{}'",
file.display(),
));
}
if let Some(file) = target_file {
err.note(format!(
"the full name for the target type has been written to '{}'",
"the full name for the type has been written to '{}'",
file.display(),
));
}
@ -3184,9 +3186,9 @@ fn note_obligation_cause_code<T>(
// Don't print the tuple of capture types
'print: {
if !is_upvar_tys_infer_tuple {
let msg = with_forced_trimmed_paths!(format!(
"required because it appears within the type `{ty}`",
));
let mut file = None;
let ty_str = self.tcx.short_ty_string(ty, &mut file);
let msg = format!("required because it appears within the type `{ty_str}`");
match ty.kind() {
ty::Adt(def, _) => match self.tcx.opt_item_ident(def.did()) {
Some(ident) => err.span_note(ident.span, msg),
@ -3283,8 +3285,9 @@ fn note_obligation_cause_code<T>(
let mut parent_trait_pred =
self.resolve_vars_if_possible(data.derived.parent_trait_pred);
let parent_def_id = parent_trait_pred.def_id();
let (self_ty, file) =
self.tcx.short_ty_string(parent_trait_pred.skip_binder().self_ty());
let mut file = None;
let self_ty =
self.tcx.short_ty_string(parent_trait_pred.skip_binder().self_ty(), &mut file);
let msg = format!(
"required for `{self_ty}` to implement `{}`",
parent_trait_pred.print_modifiers_and_trait_path()
@ -3381,8 +3384,10 @@ fn note_obligation_cause_code<T>(
count,
pluralize!(count)
));
let (self_ty, file) =
self.tcx.short_ty_string(parent_trait_pred.skip_binder().self_ty());
let mut file = None;
let self_ty = self
.tcx
.short_ty_string(parent_trait_pred.skip_binder().self_ty(), &mut file);
err.note(format!(
"required for `{self_ty}` to implement `{}`",
parent_trait_pred.print_modifiers_and_trait_path()
@ -4707,6 +4712,7 @@ fn visit_ty(&mut self, t: &'hir hir::Ty<'hir>) {
}
pub(super) fn get_explanation_based_on_obligation<'tcx>(
tcx: TyCtxt<'tcx>,
obligation: &PredicateObligation<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
trait_predicate: &ty::PolyTraitPredicate<'tcx>,
@ -4727,13 +4733,13 @@ pub(super) fn get_explanation_based_on_obligation<'tcx>(
pre_message,
trait_predicate.print_modifiers_and_trait_path(),
desc,
trait_ref.skip_binder().self_ty(),
tcx.short_ty_string(trait_ref.skip_binder().self_ty(), &mut None),
),
None => format!(
"{}the trait `{}` is not implemented for `{}`",
pre_message,
trait_predicate.print_modifiers_and_trait_path(),
trait_ref.skip_binder().self_ty(),
tcx.short_ty_string(trait_ref.skip_binder().self_ty(), &mut None),
),
}
}

View file

@ -444,21 +444,22 @@ fn report_selection_error(
// reported on the binding definition (#56607).
return;
}
let (post_message, pre_message, type_def, file_note) = self
let mut file = None;
let (post_message, pre_message, type_def) = self
.get_parent_trait_ref(obligation.cause.code())
.map(|(t, s)| {
let (t, file) = self.tcx.short_ty_string(t);
let t = self.tcx.short_ty_string(t, &mut file);
(
format!(" in `{t}`"),
format!("within `{t}`, "),
s.map(|s| (format!("within this `{t}`"), s)),
file.map(|file| format!(
"the full trait has been written to '{}'",
file.display(),
))
)
})
.unwrap_or_default();
let file_note = file.map(|file| format!(
"the full trait has been written to '{}'",
file.display(),
));
let OnUnimplementedNote {
message,
@ -547,6 +548,7 @@ fn report_selection_error(
}
let explanation = get_explanation_based_on_obligation(
self.tcx,
&obligation,
trait_ref,
&trait_predicate,

View file

@ -19,9 +19,8 @@ LL | | ))))))))))))))))))))))))))))));
| |__________________________________^ expected `Atype<Btype<..., ...>, ...>`, found `Result<Result<..., ...>, ...>`
|
= note: expected struct `Atype<Btype<..., ...>, ...>`
the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
found enum `Result<Result<..., ...>, ...>`
the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
= note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
error[E0308]: mismatched types
--> $DIR/long-E0308.rs:57:26
@ -35,9 +34,8 @@ LL | | ))))))))))))))))))))))));
| |____________________________^ expected `Option<Result<..., ...>>`, found `Result<Result<..., ...>, ...>`
|
= note: expected enum `Option<Result<..., ...>>`
the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
found enum `Result<Result<..., ...>, ...>`
the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
= note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
error[E0308]: mismatched types
--> $DIR/long-E0308.rs:88:9
@ -55,8 +53,8 @@ LL | | > = ();
| expected due to this
|
= note: expected struct `Atype<Btype<..., ...>, ...>`
the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
found unit type `()`
= note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
error[E0308]: mismatched types
--> $DIR/long-E0308.rs:91:17
@ -73,7 +71,7 @@ LL | | ))))))))))))))))))))))));
|
= note: expected unit type `()`
found enum `Result<Result<..., ...>, ...>`
the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
= note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
error: aborting due to 4 previous errors

View file

@ -95,7 +95,7 @@ LL | fn unsized_local() where Dst<dyn A>: Sized {
| ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `Dst<(dyn A + 'static)>`, the trait `Sized` is not implemented for `(dyn A + 'static)`
note: required because it appears within the type `Dst<dyn A>`
note: required because it appears within the type `Dst<(dyn A + 'static)>`
--> $DIR/feature-gate-trivial_bounds.rs:48:8
|
LL | struct Dst<X: ?Sized> {

View file

@ -8,9 +8,9 @@ LL | send(format_args!("{:?}", c));
|
= help: within `[core::fmt::rt::Argument<'_>]`, the trait `Sync` is not implemented for `core::fmt::rt::Opaque`
= note: required because it appears within the type `&core::fmt::rt::Opaque`
note: required because it appears within the type `Argument<'_>`
note: required because it appears within the type `core::fmt::rt::Argument<'_>`
--> $SRC_DIR/core/src/fmt/rt.rs:LL:COL
= note: required because it appears within the type `[Argument<'_>]`
= note: required because it appears within the type `[core::fmt::rt::Argument<'_>]`
= note: required for `&[core::fmt::rt::Argument<'_>]` to implement `Send`
note: required because it appears within the type `Arguments<'_>`
--> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
@ -30,10 +30,10 @@ LL | sync(format_args!("{:?}", c));
|
= help: within `Arguments<'_>`, the trait `Sync` is not implemented for `core::fmt::rt::Opaque`
= note: required because it appears within the type `&core::fmt::rt::Opaque`
note: required because it appears within the type `Argument<'_>`
note: required because it appears within the type `core::fmt::rt::Argument<'_>`
--> $SRC_DIR/core/src/fmt/rt.rs:LL:COL
= note: required because it appears within the type `[Argument<'_>]`
= note: required because it appears within the type `&[Argument<'_>]`
= note: required because it appears within the type `[core::fmt::rt::Argument<'_>]`
= note: required because it appears within the type `&[core::fmt::rt::Argument<'_>]`
note: required because it appears within the type `Arguments<'_>`
--> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
note: required by a bound in `sync`

View file

@ -19,7 +19,7 @@ LL | foo::<for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a), _>(None, (&()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)`, the trait `for<'a> Sized` is not implemented for `(dyn std::fmt::Display + 'a)`
= note: required because it appears within the type `fn(&()) -> dyn Display`
= note: required because it appears within the type `for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a)`
note: required by a bound in `foo`
--> $DIR/unsized-ret.rs:5:11
|

View file

@ -16,7 +16,7 @@ LL | fn fuz() -> (usize, Trait) { (42, Struct) }
| doesn't have a size known at compile-time
|
= help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)`
= note: required because it appears within the type `(usize, dyn Trait)`
= note: required because it appears within the type `(usize, (dyn Trait + 'static))`
= note: the return type of a function must have a statically known size
error[E0308]: mismatched types
@ -37,7 +37,7 @@ LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
| doesn't have a size known at compile-time
|
= help: within `(usize, (dyn Trait + 'static))`, the trait `Sized` is not implemented for `(dyn Trait + 'static)`
= note: required because it appears within the type `(usize, dyn Trait)`
= note: required because it appears within the type `(usize, (dyn Trait + 'static))`
= note: the return type of a function must have a statically known size
error[E0746]: return type cannot have an unboxed trait object

View file

@ -7,7 +7,7 @@ LL | foo::<HashMap<Rc<()>, Rc<()>>>();
= help: within `(Rc<()>, Rc<()>)`, the trait `Send` is not implemented for `Rc<()>`
= note: required because it appears within the type `(Rc<()>, Rc<()>)`
= note: required for `hashbrown::raw::RawTable<(Rc<()>, Rc<()>)>` to implement `Send`
note: required because it appears within the type `HashMap<Rc<()>, Rc<()>, RandomState>`
note: required because it appears within the type `hashbrown::map::HashMap<Rc<()>, Rc<()>, RandomState>`
--> $HASHBROWN_SRC_LOCATION
note: required because it appears within the type `HashMap<Rc<()>, Rc<()>>`
--> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL

View file

@ -20,7 +20,7 @@ LL | assert_send::<Box<dyn Dummy + 'a>>();
|
= help: the trait `Send` is not implemented for `(dyn Dummy + 'a)`
= note: required for `Unique<(dyn Dummy + 'a)>` to implement `Send`
note: required because it appears within the type `Box<dyn Dummy>`
note: required because it appears within the type `Box<(dyn Dummy + 'a)>`
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
note: required by a bound in `assert_send`
--> $DIR/kindck-send-object1.rs:5:18

View file

@ -50,7 +50,7 @@ LL | is_send((8, TestType));
| required by a bound introduced by this call
|
= help: within `({integer}, dummy1c::TestType)`, the trait `Send` is not implemented for `dummy1c::TestType`
= note: required because it appears within the type `({integer}, TestType)`
= note: required because it appears within the type `({integer}, dummy1c::TestType)`
note: required by a bound in `is_send`
--> $DIR/negated-auto-traits-error.rs:16:15
|
@ -67,7 +67,7 @@ LL | is_send(Box::new(TestType));
|
= note: the trait bound `Unique<dummy2::TestType>: Send` is not satisfied
= note: required for `Unique<dummy2::TestType>` to implement `Send`
note: required because it appears within the type `Box<TestType>`
note: required because it appears within the type `Box<dummy2::TestType>`
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
note: required by a bound in `is_send`
--> $DIR/negated-auto-traits-error.rs:16:15
@ -88,13 +88,13 @@ LL | is_send(Box::new(Outer2(TestType)));
| required by a bound introduced by this call
|
= help: within `Outer2<dummy3::TestType>`, the trait `Send` is not implemented for `dummy3::TestType`
note: required because it appears within the type `Outer2<TestType>`
note: required because it appears within the type `Outer2<dummy3::TestType>`
--> $DIR/negated-auto-traits-error.rs:12:8
|
LL | struct Outer2<T>(T);
| ^^^^^^
= note: required for `Unique<Outer2<dummy3::TestType>>` to implement `Send`
note: required because it appears within the type `Box<Outer2<TestType>>`
note: required because it appears within the type `Box<Outer2<dummy3::TestType>>`
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
note: required by a bound in `is_send`
--> $DIR/negated-auto-traits-error.rs:16:15