Rollup merge of #126142 - compiler-errors:trait-ref-split, r=jackh726

Harmonize using root or leaf obligation in trait error reporting

When #121826 changed the error reporting to use root obligation and not the leafmost obligation, it didn't actually make sure that all the other diagnostics helper functions used the right obligation.

Specifically, when reporting similar impl candidates we are looking for impls of the root obligation, but trying to match them against the trait ref of the leaf obligation.

This does a few other miscellaneous changes. There's a lot more clean-up that could be done here, but working with this code is really grief-inducing due to how messy it has become over the years. Someone really needs to show it love. 😓

r? ``@estebank``

Fixes #126129
This commit is contained in:
Jubilee 2024-06-12 20:03:19 -07:00 committed by GitHub
commit 25c55c51cb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 163 additions and 119 deletions

View File

@ -546,7 +546,7 @@ fn suggest_constraint(
for pred in hir_generics.bounds_for_param(def_id) { for pred in hir_generics.bounds_for_param(def_id) {
if self.constrain_generic_bound_associated_type_structured_suggestion( if self.constrain_generic_bound_associated_type_structured_suggestion(
diag, diag,
&trait_ref, trait_ref,
pred.bounds, pred.bounds,
assoc, assoc,
assoc_args, assoc_args,
@ -715,7 +715,7 @@ fn suggest_constraining_opaque_associated_type(
self.constrain_generic_bound_associated_type_structured_suggestion( self.constrain_generic_bound_associated_type_structured_suggestion(
diag, diag,
&trait_ref, trait_ref,
opaque_hir_ty.bounds, opaque_hir_ty.bounds,
assoc, assoc,
assoc_args, assoc_args,
@ -869,7 +869,7 @@ trait defining them",
fn constrain_generic_bound_associated_type_structured_suggestion( fn constrain_generic_bound_associated_type_structured_suggestion(
&self, &self,
diag: &mut Diag<'_>, diag: &mut Diag<'_>,
trait_ref: &ty::TraitRef<'tcx>, trait_ref: ty::TraitRef<'tcx>,
bounds: hir::GenericBounds<'_>, bounds: hir::GenericBounds<'_>,
assoc: ty::AssocItem, assoc: ty::AssocItem,
assoc_args: &[ty::GenericArg<'tcx>], assoc_args: &[ty::GenericArg<'tcx>],

View File

@ -285,8 +285,7 @@ fn elaborate(&mut self, elaboratable: &O) {
let obligations = let obligations =
predicates.predicates.iter().enumerate().map(|(index, &(clause, span))| { predicates.predicates.iter().enumerate().map(|(index, &(clause, span))| {
elaboratable.child_with_derived_cause( elaboratable.child_with_derived_cause(
clause clause.instantiate_supertrait(tcx, bound_clause.rebind(data.trait_ref)),
.instantiate_supertrait(tcx, &bound_clause.rebind(data.trait_ref)),
span, span,
bound_clause.rebind(data), bound_clause.rebind(data),
index, index,

View File

@ -37,7 +37,7 @@ fn elaborate(&mut self, trait_ref: PolyTraitRef<'tcx>) {
let super_predicates = let super_predicates =
self.tcx.super_predicates_of(trait_ref.def_id()).predicates.iter().filter_map( self.tcx.super_predicates_of(trait_ref.def_id()).predicates.iter().filter_map(
|&(pred, _)| { |&(pred, _)| {
let clause = pred.instantiate_supertrait(self.tcx, &trait_ref); let clause = pred.instantiate_supertrait(self.tcx, trait_ref);
self.visited.insert(clause).then_some(clause) self.visited.insert(clause).then_some(clause)
}, },
); );

View File

@ -313,7 +313,7 @@ impl<'tcx> Clause<'tcx> {
pub fn instantiate_supertrait( pub fn instantiate_supertrait(
self, self,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
trait_ref: &ty::PolyTraitRef<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>,
) -> Clause<'tcx> { ) -> Clause<'tcx> {
// The interaction between HRTB and supertraits is not entirely // The interaction between HRTB and supertraits is not entirely
// obvious. Let me walk you (and myself) through an example. // obvious. Let me walk you (and myself) through an example.

View File

@ -3597,7 +3597,7 @@ fn suggest_floating_point_literal(
&self, &self,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
err: &mut Diag<'_>, err: &mut Diag<'_>,
trait_ref: &ty::PolyTraitRef<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>,
) { ) {
let rhs_span = match obligation.cause.code() { let rhs_span = match obligation.cause.code() {
ObligationCauseCode::BinOp { rhs_span: Some(span), rhs_is_lit, .. } if *rhs_is_lit => { ObligationCauseCode::BinOp { rhs_span: Some(span), rhs_is_lit, .. } if *rhs_is_lit => {
@ -4592,7 +4592,7 @@ fn suggest_add_result_as_return_type(
&self, &self,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
err: &mut Diag<'_>, err: &mut Diag<'_>,
trait_ref: ty::PolyTraitRef<'tcx>, trait_pred: ty::PolyTraitPredicate<'tcx>,
) { ) {
if ObligationCauseCode::QuestionMark != *obligation.cause.code().peel_derives() { if ObligationCauseCode::QuestionMark != *obligation.cause.code().peel_derives() {
return; return;
@ -4602,10 +4602,9 @@ fn suggest_add_result_as_return_type(
if let hir::Node::Item(item) = node if let hir::Node::Item(item) = node
&& let hir::ItemKind::Fn(sig, _, body_id) = item.kind && let hir::ItemKind::Fn(sig, _, body_id) = item.kind
&& let hir::FnRetTy::DefaultReturn(ret_span) = sig.decl.output && let hir::FnRetTy::DefaultReturn(ret_span) = sig.decl.output
&& self.tcx.is_diagnostic_item(sym::FromResidual, trait_ref.def_id()) && self.tcx.is_diagnostic_item(sym::FromResidual, trait_pred.def_id())
&& let ty::Tuple(l) = trait_ref.skip_binder().args.type_at(0).kind() && trait_pred.skip_binder().trait_ref.args.type_at(0).is_unit()
&& l.len() == 0 && let ty::Adt(def, _) = trait_pred.skip_binder().trait_ref.args.type_at(1).kind()
&& let ty::Adt(def, _) = trait_ref.skip_binder().args.type_at(1).kind()
&& self.tcx.is_diagnostic_item(sym::Result, def.did()) && self.tcx.is_diagnostic_item(sym::Result, def.did())
{ {
let body = self.tcx.hir().body(body_id); let body = self.tcx.hir().body(body_id);
@ -4863,14 +4862,13 @@ fn visit_ty(&mut self, t: &'hir hir::Ty<'hir>) {
pub(super) fn get_explanation_based_on_obligation<'tcx>( pub(super) fn get_explanation_based_on_obligation<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>, trait_predicate: ty::PolyTraitPredicate<'tcx>,
trait_predicate: &ty::PolyTraitPredicate<'tcx>,
pre_message: String, pre_message: String,
) -> String { ) -> String {
if let ObligationCauseCode::MainFunctionType = obligation.cause.code() { if let ObligationCauseCode::MainFunctionType = obligation.cause.code() {
"consider using `()`, or a `Result`".to_owned() "consider using `()`, or a `Result`".to_owned()
} else { } else {
let ty_desc = match trait_ref.skip_binder().self_ty().kind() { let ty_desc = match trait_predicate.self_ty().skip_binder().kind() {
ty::FnDef(_, _) => Some("fn item"), ty::FnDef(_, _) => Some("fn item"),
ty::Closure(_, _) => Some("closure"), ty::Closure(_, _) => Some("closure"),
_ => None, _ => None,
@ -4895,7 +4893,7 @@ pub(super) fn get_explanation_based_on_obligation<'tcx>(
format!( format!(
"{pre_message}the trait `{}` is not implemented for{desc} `{}`{post}", "{pre_message}the trait `{}` is not implemented for{desc} `{}`{post}",
trait_predicate.print_modifiers_and_trait_path(), trait_predicate.print_modifiers_and_trait_path(),
tcx.short_ty_string(trait_ref.skip_binder().self_ty(), &mut None), tcx.short_ty_string(trait_predicate.self_ty().skip_binder(), &mut None),
) )
} else { } else {
// "the trait bound `T: !Send` is not satisfied" reads better than "`!Send` is // "the trait bound `T: !Send` is not satisfied" reads better than "`!Send` is

View File

@ -412,8 +412,8 @@ fn report_selection_error(
let bound_predicate = obligation.predicate.kind(); let bound_predicate = obligation.predicate.kind();
match bound_predicate.skip_binder() { match bound_predicate.skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => { ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {
let trait_predicate = bound_predicate.rebind(trait_predicate); let leaf_trait_predicate =
let trait_predicate = self.resolve_vars_if_possible(trait_predicate); self.resolve_vars_if_possible(bound_predicate.rebind(trait_predicate));
// Let's use the root obligation as the main message, when we care about the // Let's use the root obligation as the main message, when we care about the
// most general case ("X doesn't implement Pattern<'_>") over the case that // most general case ("X doesn't implement Pattern<'_>") over the case that
@ -424,7 +424,7 @@ fn report_selection_error(
let (main_trait_predicate, o) = if let ty::PredicateKind::Clause( let (main_trait_predicate, o) = if let ty::PredicateKind::Clause(
ty::ClauseKind::Trait(root_pred) ty::ClauseKind::Trait(root_pred)
) = root_obligation.predicate.kind().skip_binder() ) = root_obligation.predicate.kind().skip_binder()
&& !trait_predicate.self_ty().skip_binder().has_escaping_bound_vars() && !leaf_trait_predicate.self_ty().skip_binder().has_escaping_bound_vars()
&& !root_pred.self_ty().has_escaping_bound_vars() && !root_pred.self_ty().has_escaping_bound_vars()
// The type of the leaf predicate is (roughly) the same as the type // The type of the leaf predicate is (roughly) the same as the type
// from the root predicate, as a proxy for "we care about the root" // from the root predicate, as a proxy for "we care about the root"
@ -434,20 +434,20 @@ fn report_selection_error(
// `T: Trait` && `&&T: OtherTrait`, we want `OtherTrait` // `T: Trait` && `&&T: OtherTrait`, we want `OtherTrait`
self.can_eq( self.can_eq(
obligation.param_env, obligation.param_env,
trait_predicate.self_ty().skip_binder(), leaf_trait_predicate.self_ty().skip_binder(),
root_pred.self_ty().peel_refs(), root_pred.self_ty().peel_refs(),
) )
// `&str: Iterator` && `&str: IntoIterator`, we want `IntoIterator` // `&str: Iterator` && `&str: IntoIterator`, we want `IntoIterator`
|| self.can_eq( || self.can_eq(
obligation.param_env, obligation.param_env,
trait_predicate.self_ty().skip_binder(), leaf_trait_predicate.self_ty().skip_binder(),
root_pred.self_ty(), root_pred.self_ty(),
) )
) )
// The leaf trait and the root trait are different, so as to avoid // The leaf trait and the root trait are different, so as to avoid
// talking about `&mut T: Trait` and instead remain talking about // talking about `&mut T: Trait` and instead remain talking about
// `T: Trait` instead // `T: Trait` instead
&& trait_predicate.def_id() != root_pred.def_id() && leaf_trait_predicate.def_id() != root_pred.def_id()
// The root trait is not `Unsize`, as to avoid talking about it in // The root trait is not `Unsize`, as to avoid talking about it in
// `tests/ui/coercion/coerce-issue-49593-box-never.rs`. // `tests/ui/coercion/coerce-issue-49593-box-never.rs`.
&& Some(root_pred.def_id()) != self.tcx.lang_items().unsize_trait() && Some(root_pred.def_id()) != self.tcx.lang_items().unsize_trait()
@ -459,13 +459,14 @@ fn report_selection_error(
root_obligation, root_obligation,
) )
} else { } else {
(trait_predicate, &obligation) (leaf_trait_predicate, &obligation)
}; };
let trait_ref = main_trait_predicate.to_poly_trait_ref(); let main_trait_ref = main_trait_predicate.to_poly_trait_ref();
let leaf_trait_ref = leaf_trait_predicate.to_poly_trait_ref();
if let Some(guar) = self.emit_specialized_closure_kind_error( if let Some(guar) = self.emit_specialized_closure_kind_error(
&obligation, &obligation,
trait_ref, leaf_trait_ref,
) { ) {
return guar; return guar;
} }
@ -473,7 +474,7 @@ fn report_selection_error(
// FIXME(effects) // FIXME(effects)
let predicate_is_const = false; let predicate_is_const = false;
if let Err(guar) = trait_predicate.error_reported() if let Err(guar) = leaf_trait_predicate.error_reported()
{ {
return guar; return guar;
} }
@ -507,16 +508,17 @@ fn report_selection_error(
notes, notes,
parent_label, parent_label,
append_const_msg, append_const_msg,
} = self.on_unimplemented_note(trait_ref, o, &mut long_ty_file); } = self.on_unimplemented_note(main_trait_ref, o, &mut long_ty_file);
let have_alt_message = message.is_some() || label.is_some(); let have_alt_message = message.is_some() || label.is_some();
let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id()); let is_try_conversion = self.is_try_conversion(span, main_trait_ref.def_id());
let is_unsize = let is_unsize =
Some(trait_ref.def_id()) == self.tcx.lang_items().unsize_trait(); Some(leaf_trait_ref.def_id()) == self.tcx.lang_items().unsize_trait();
let (message, notes, append_const_msg) = if is_try_conversion { let (message, notes, append_const_msg) = if is_try_conversion {
( (
Some(format!( Some(format!(
"`?` couldn't convert the error to `{}`", "`?` couldn't convert the error to `{}`",
trait_ref.skip_binder().self_ty(), main_trait_ref.skip_binder().self_ty(),
)), )),
vec![ vec![
"the question mark operation (`?`) implicitly performs a \ "the question mark operation (`?`) implicitly performs a \
@ -530,20 +532,20 @@ fn report_selection_error(
}; };
let err_msg = self.get_standard_error_message( let err_msg = self.get_standard_error_message(
&main_trait_predicate, main_trait_predicate,
message, message,
predicate_is_const, predicate_is_const,
append_const_msg, append_const_msg,
post_message, post_message,
); );
let (err_msg, safe_transmute_explanation) = if Some(trait_ref.def_id()) let (err_msg, safe_transmute_explanation) = if Some(main_trait_ref.def_id())
== self.tcx.lang_items().transmute_trait() == self.tcx.lang_items().transmute_trait()
{ {
// Recompute the safe transmute reason and use that for the error reporting // Recompute the safe transmute reason and use that for the error reporting
match self.get_safe_transmute_error_and_reason( match self.get_safe_transmute_error_and_reason(
obligation.clone(), obligation.clone(),
trait_ref, main_trait_ref,
span, span,
) { ) {
GetSafeTransmuteErrorAndReason::Silent => { GetSafeTransmuteErrorAndReason::Silent => {
@ -571,7 +573,7 @@ fn report_selection_error(
} }
let mut suggested = false; let mut suggested = false;
if is_try_conversion { if is_try_conversion {
suggested = self.try_conversion_context(&obligation, trait_ref.skip_binder(), &mut err); suggested = self.try_conversion_context(&obligation, main_trait_ref.skip_binder(), &mut err);
} }
if is_try_conversion && let Some(ret_span) = self.return_type_span(&obligation) { if is_try_conversion && let Some(ret_span) = self.return_type_span(&obligation) {
@ -579,19 +581,19 @@ fn report_selection_error(
ret_span, ret_span,
format!( format!(
"expected `{}` because of this", "expected `{}` because of this",
trait_ref.skip_binder().self_ty() main_trait_ref.skip_binder().self_ty()
), ),
); );
} }
if Some(trait_ref.def_id()) == tcx.lang_items().tuple_trait() { if Some(leaf_trait_ref.def_id()) == tcx.lang_items().tuple_trait() {
self.add_tuple_trait_message( self.add_tuple_trait_message(
obligation.cause.code().peel_derives(), obligation.cause.code().peel_derives(),
&mut err, &mut err,
); );
} }
if Some(trait_ref.def_id()) == tcx.lang_items().drop_trait() if Some(leaf_trait_ref.def_id()) == tcx.lang_items().drop_trait()
&& predicate_is_const && predicate_is_const
{ {
err.note("`~const Drop` was renamed to `~const Destruct`"); err.note("`~const Drop` was renamed to `~const Destruct`");
@ -601,24 +603,25 @@ fn report_selection_error(
let explanation = get_explanation_based_on_obligation( let explanation = get_explanation_based_on_obligation(
self.tcx, self.tcx,
&obligation, &obligation,
trait_ref, leaf_trait_predicate,
&trait_predicate,
pre_message, pre_message,
); );
self.check_for_binding_assigned_block_without_tail_expression( self.check_for_binding_assigned_block_without_tail_expression(
&obligation, &obligation,
&mut err, &mut err,
trait_predicate, leaf_trait_predicate,
); );
self.suggest_add_result_as_return_type(&obligation, self.suggest_add_result_as_return_type(
&obligation,
&mut err, &mut err,
trait_ref); leaf_trait_predicate,
);
if self.suggest_add_reference_to_arg( if self.suggest_add_reference_to_arg(
&obligation, &obligation,
&mut err, &mut err,
trait_predicate, leaf_trait_predicate,
have_alt_message, have_alt_message,
) { ) {
self.note_obligation_cause(&mut err, &obligation); self.note_obligation_cause(&mut err, &obligation);
@ -630,7 +633,7 @@ fn report_selection_error(
// If it has a custom `#[rustc_on_unimplemented]` // If it has a custom `#[rustc_on_unimplemented]`
// error message, let's display it as the label! // error message, let's display it as the label!
err.span_label(span, s); err.span_label(span, s);
if !matches!(trait_ref.skip_binder().self_ty().kind(), ty::Param(_)) { if !matches!(leaf_trait_ref.skip_binder().self_ty().kind(), ty::Param(_)) {
// When the self type is a type param We don't need to "the trait // When the self type is a type param We don't need to "the trait
// `std::marker::Sized` is not implemented for `T`" as we will point // `std::marker::Sized` is not implemented for `T`" as we will point
// at the type param with a label to suggest constraining it. // at the type param with a label to suggest constraining it.
@ -645,7 +648,7 @@ fn report_selection_error(
if let ObligationCauseCode::Coercion { source, target } = if let ObligationCauseCode::Coercion { source, target } =
*obligation.cause.code().peel_derives() *obligation.cause.code().peel_derives()
{ {
if Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() { if Some(leaf_trait_ref.def_id()) == self.tcx.lang_items().sized_trait() {
self.suggest_borrowing_for_object_cast( self.suggest_borrowing_for_object_cast(
&mut err, &mut err,
root_obligation, root_obligation,
@ -657,7 +660,7 @@ fn report_selection_error(
let UnsatisfiedConst(unsatisfied_const) = self let UnsatisfiedConst(unsatisfied_const) = self
.maybe_add_note_for_unsatisfied_const( .maybe_add_note_for_unsatisfied_const(
&trait_predicate, leaf_trait_predicate,
&mut err, &mut err,
span, span,
); );
@ -674,15 +677,15 @@ fn report_selection_error(
err.span_label(tcx.def_span(body), s); err.span_label(tcx.def_span(body), s);
} }
self.suggest_floating_point_literal(&obligation, &mut err, &trait_ref); self.suggest_floating_point_literal(&obligation, &mut err, leaf_trait_ref);
self.suggest_dereferencing_index(&obligation, &mut err, trait_predicate); self.suggest_dereferencing_index(&obligation, &mut err, leaf_trait_predicate);
suggested |= self.suggest_dereferences(&obligation, &mut err, trait_predicate); suggested |= self.suggest_dereferences(&obligation, &mut err, leaf_trait_predicate);
suggested |= self.suggest_fn_call(&obligation, &mut err, trait_predicate); suggested |= self.suggest_fn_call(&obligation, &mut err, leaf_trait_predicate);
let impl_candidates = self.find_similar_impl_candidates(trait_predicate); let impl_candidates = self.find_similar_impl_candidates(leaf_trait_predicate);
suggested = if let &[cand] = &impl_candidates[..] { suggested = if let &[cand] = &impl_candidates[..] {
let cand = cand.trait_ref; let cand = cand.trait_ref;
if let (ty::FnPtr(_), ty::FnDef(..)) = if let (ty::FnPtr(_), ty::FnDef(..)) =
(cand.self_ty().kind(), trait_ref.self_ty().skip_binder().kind()) (cand.self_ty().kind(), main_trait_ref.self_ty().skip_binder().kind())
{ {
err.span_suggestion( err.span_suggestion(
span.shrink_to_hi(), span.shrink_to_hi(),
@ -702,31 +705,31 @@ fn report_selection_error(
false false
} || suggested; } || suggested;
suggested |= suggested |=
self.suggest_remove_reference(&obligation, &mut err, trait_predicate); self.suggest_remove_reference(&obligation, &mut err, leaf_trait_predicate);
suggested |= self.suggest_semicolon_removal( suggested |= self.suggest_semicolon_removal(
&obligation, &obligation,
&mut err, &mut err,
span, span,
trait_predicate, leaf_trait_predicate,
); );
self.note_version_mismatch(&mut err, &trait_ref); self.note_version_mismatch(&mut err, leaf_trait_ref);
self.suggest_remove_await(&obligation, &mut err); self.suggest_remove_await(&obligation, &mut err);
self.suggest_derive(&obligation, &mut err, trait_predicate); self.suggest_derive(&obligation, &mut err, leaf_trait_predicate);
if Some(trait_ref.def_id()) == tcx.lang_items().try_trait() { if Some(leaf_trait_ref.def_id()) == tcx.lang_items().try_trait() {
self.suggest_await_before_try( self.suggest_await_before_try(
&mut err, &mut err,
&obligation, &obligation,
trait_predicate, leaf_trait_predicate,
span, span,
); );
} }
if self.suggest_add_clone_to_arg(&obligation, &mut err, trait_predicate) { if self.suggest_add_clone_to_arg(&obligation, &mut err, leaf_trait_predicate) {
return err.emit(); return err.emit();
} }
if self.suggest_impl_trait(&mut err, &obligation, trait_predicate) { if self.suggest_impl_trait(&mut err, &obligation, leaf_trait_predicate) {
return err.emit(); return err.emit();
} }
@ -741,9 +744,9 @@ fn report_selection_error(
); );
} }
let is_fn_trait = tcx.is_fn_trait(trait_ref.def_id()); let is_fn_trait = tcx.is_fn_trait(leaf_trait_ref.def_id());
let is_target_feature_fn = if let ty::FnDef(def_id, _) = let is_target_feature_fn = if let ty::FnDef(def_id, _) =
*trait_ref.skip_binder().self_ty().kind() *leaf_trait_ref.skip_binder().self_ty().kind()
{ {
!self.tcx.codegen_fn_attrs(def_id).target_features.is_empty() !self.tcx.codegen_fn_attrs(def_id).target_features.is_empty()
} else { } else {
@ -757,8 +760,7 @@ fn report_selection_error(
self.try_to_add_help_message( self.try_to_add_help_message(
&obligation, &obligation,
trait_ref, leaf_trait_predicate,
&trait_predicate,
&mut err, &mut err,
span, span,
is_fn_trait, is_fn_trait,
@ -769,17 +771,17 @@ fn report_selection_error(
// Changing mutability doesn't make a difference to whether we have // Changing mutability doesn't make a difference to whether we have
// an `Unsize` impl (Fixes ICE in #71036) // an `Unsize` impl (Fixes ICE in #71036)
if !is_unsize { if !is_unsize {
self.suggest_change_mut(&obligation, &mut err, trait_predicate); self.suggest_change_mut(&obligation, &mut err, leaf_trait_predicate);
} }
// If this error is due to `!: Trait` not implemented but `(): Trait` is // If this error is due to `!: Trait` not implemented but `(): Trait` is
// implemented, and fallback has occurred, then it could be due to a // implemented, and fallback has occurred, then it could be due to a
// variable that used to fallback to `()` now falling back to `!`. Issue a // variable that used to fallback to `()` now falling back to `!`. Issue a
// note informing about the change in behaviour. // note informing about the change in behaviour.
if trait_predicate.skip_binder().self_ty().is_never() if leaf_trait_predicate.skip_binder().self_ty().is_never()
&& self.fallback_has_occurred && self.fallback_has_occurred
{ {
let predicate = trait_predicate.map_bound(|trait_pred| { let predicate = leaf_trait_predicate.map_bound(|trait_pred| {
trait_pred.with_self_ty(self.tcx, tcx.types.unit) trait_pred.with_self_ty(self.tcx, tcx.types.unit)
}); });
let unit_obligation = obligation.with(tcx, predicate); let unit_obligation = obligation.with(tcx, predicate);
@ -794,8 +796,8 @@ fn report_selection_error(
} }
} }
self.explain_hrtb_projection(&mut err, trait_predicate, obligation.param_env, &obligation.cause); self.explain_hrtb_projection(&mut err, leaf_trait_predicate, obligation.param_env, &obligation.cause);
self.suggest_desugaring_async_fn_in_trait(&mut err, trait_ref); self.suggest_desugaring_async_fn_in_trait(&mut err, main_trait_ref);
// Return early if the trait is Debug or Display and the invocation // Return early if the trait is Debug or Display and the invocation
// originates within a standard library macro, because the output // originates within a standard library macro, because the output
@ -813,15 +815,13 @@ fn report_selection_error(
if in_std_macro if in_std_macro
&& matches!( && matches!(
self.tcx.get_diagnostic_name(trait_ref.def_id()), self.tcx.get_diagnostic_name(leaf_trait_ref.def_id()),
Some(sym::Debug | sym::Display) Some(sym::Debug | sym::Display)
) )
{ {
return err.emit(); return err.emit();
} }
err err
} }
@ -2236,11 +2236,7 @@ fn get_parent_trait_ref(
/// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
/// with the same path as `trait_ref`, a help message about /// with the same path as `trait_ref`, a help message about
/// a probable version mismatch is added to `err` /// a probable version mismatch is added to `err`
fn note_version_mismatch( fn note_version_mismatch(&self, err: &mut Diag<'_>, trait_ref: ty::PolyTraitRef<'tcx>) -> bool {
&self,
err: &mut Diag<'_>,
trait_ref: &ty::PolyTraitRef<'tcx>,
) -> bool {
let get_trait_impls = |trait_def_id| { let get_trait_impls = |trait_def_id| {
let mut trait_impls = vec![]; let mut trait_impls = vec![];
self.tcx.for_each_relevant_impl( self.tcx.for_each_relevant_impl(
@ -3060,7 +3056,7 @@ fn is_recursive_obligation(
fn get_standard_error_message( fn get_standard_error_message(
&self, &self,
trait_predicate: &ty::PolyTraitPredicate<'tcx>, trait_predicate: ty::PolyTraitPredicate<'tcx>,
message: Option<String>, message: Option<String>,
predicate_is_const: bool, predicate_is_const: bool,
append_const_msg: Option<AppendConstMessage>, append_const_msg: Option<AppendConstMessage>,
@ -3231,8 +3227,7 @@ fn add_tuple_trait_message(
fn try_to_add_help_message( fn try_to_add_help_message(
&self, &self,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>, trait_predicate: ty::PolyTraitPredicate<'tcx>,
trait_predicate: &ty::PolyTraitPredicate<'tcx>,
err: &mut Diag<'_>, err: &mut Diag<'_>,
span: Span, span: Span,
is_fn_trait: bool, is_fn_trait: bool,
@ -3249,16 +3244,22 @@ fn try_to_add_help_message(
}; };
// Try to report a help message // Try to report a help message
let trait_def_id = trait_predicate.def_id();
if is_fn_trait if is_fn_trait
&& let Ok((implemented_kind, params)) = self.type_implements_fn_trait( && let Ok((implemented_kind, params)) = self.type_implements_fn_trait(
obligation.param_env, obligation.param_env,
trait_ref.self_ty(), trait_predicate.self_ty(),
trait_predicate.skip_binder().polarity, trait_predicate.skip_binder().polarity,
) )
{ {
self.add_help_message_for_fn_trait(trait_ref, err, implemented_kind, params); self.add_help_message_for_fn_trait(
} else if !trait_ref.has_non_region_infer() trait_predicate.to_poly_trait_ref(),
&& self.predicate_can_apply(obligation.param_env, *trait_predicate) err,
implemented_kind,
params,
);
} else if !trait_predicate.has_non_region_infer()
&& self.predicate_can_apply(obligation.param_env, trait_predicate)
{ {
// If a where-clause may be useful, remind the // If a where-clause may be useful, remind the
// user that they can add it. // user that they can add it.
@ -3269,25 +3270,25 @@ fn try_to_add_help_message(
// which is somewhat confusing. // which is somewhat confusing.
self.suggest_restricting_param_bound( self.suggest_restricting_param_bound(
err, err,
*trait_predicate, trait_predicate,
None, None,
obligation.cause.body_id, obligation.cause.body_id,
); );
} else if trait_ref.def_id().is_local() } else if trait_def_id.is_local()
&& self.tcx.trait_impls_of(trait_ref.def_id()).is_empty() && self.tcx.trait_impls_of(trait_def_id).is_empty()
&& !self.tcx.trait_is_auto(trait_ref.def_id()) && !self.tcx.trait_is_auto(trait_def_id)
&& !self.tcx.trait_is_alias(trait_ref.def_id()) && !self.tcx.trait_is_alias(trait_def_id)
{ {
err.span_help( err.span_help(
self.tcx.def_span(trait_ref.def_id()), self.tcx.def_span(trait_def_id),
crate::fluent_generated::trait_selection_trait_has_no_impls, crate::fluent_generated::trait_selection_trait_has_no_impls,
); );
} else if !suggested && !unsatisfied_const { } else if !suggested && !unsatisfied_const {
// Can't show anything else useful, try to find similar impls. // Can't show anything else useful, try to find similar impls.
let impl_candidates = self.find_similar_impl_candidates(*trait_predicate); let impl_candidates = self.find_similar_impl_candidates(trait_predicate);
if !self.report_similar_impl_candidates( if !self.report_similar_impl_candidates(
&impl_candidates, &impl_candidates,
trait_ref, trait_predicate.to_poly_trait_ref(),
body_def_id, body_def_id,
err, err,
true, true,
@ -3295,7 +3296,7 @@ fn try_to_add_help_message(
) { ) {
self.report_similar_impl_candidates_for_root_obligation( self.report_similar_impl_candidates_for_root_obligation(
obligation, obligation,
*trait_predicate, trait_predicate,
body_def_id, body_def_id,
err, err,
); );
@ -3304,7 +3305,7 @@ fn try_to_add_help_message(
self.suggest_convert_to_slice( self.suggest_convert_to_slice(
err, err,
obligation, obligation,
trait_ref, trait_predicate.to_poly_trait_ref(),
impl_candidates.as_slice(), impl_candidates.as_slice(),
span, span,
); );
@ -3369,7 +3370,7 @@ fn add_help_message_for_fn_trait(
fn maybe_add_note_for_unsatisfied_const( fn maybe_add_note_for_unsatisfied_const(
&self, &self,
_trait_predicate: &ty::PolyTraitPredicate<'tcx>, _trait_predicate: ty::PolyTraitPredicate<'tcx>,
_err: &mut Diag<'_>, _err: &mut Diag<'_>,
_span: Span, _span: Span,
) -> UnsatisfiedConst { ) -> UnsatisfiedConst {

View File

@ -194,7 +194,7 @@ fn predicates_reference_self(
predicates predicates
.predicates .predicates
.iter() .iter()
.map(|&(predicate, sp)| (predicate.instantiate_supertrait(tcx, &trait_ref), sp)) .map(|&(predicate, sp)| (predicate.instantiate_supertrait(tcx, trait_ref), sp))
.filter_map(|predicate| predicate_references_self(tcx, predicate)) .filter_map(|predicate| predicate_references_self(tcx, predicate))
.collect() .collect()
} }

View File

@ -1866,7 +1866,7 @@ fn candidate_should_be_dropped_in_favor_of(
// the param_env so that it can be given the lowest priority. See // the param_env so that it can be given the lowest priority. See
// #50825 for the motivation for this. // #50825 for the motivation for this.
let is_global = let is_global =
|cand: &ty::PolyTraitPredicate<'tcx>| cand.is_global() && !cand.has_bound_vars(); |cand: ty::PolyTraitPredicate<'tcx>| cand.is_global() && !cand.has_bound_vars();
// (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`, // (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`,
// `DiscriminantKindCandidate`, `ConstDestructCandidate` // `DiscriminantKindCandidate`, `ConstDestructCandidate`
@ -1909,7 +1909,7 @@ fn candidate_should_be_dropped_in_favor_of(
} }
( (
ParamCandidate(ref other_cand), ParamCandidate(other_cand),
ImplCandidate(..) ImplCandidate(..)
| AutoImplCandidate | AutoImplCandidate
| ClosureCandidate { .. } | ClosureCandidate { .. }
@ -1934,12 +1934,12 @@ fn candidate_should_be_dropped_in_favor_of(
// //
// Global bounds from the where clause should be ignored // Global bounds from the where clause should be ignored
// here (see issue #50825). // here (see issue #50825).
DropVictim::drop_if(!is_global(other_cand)) DropVictim::drop_if(!is_global(*other_cand))
} }
(ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref victim_cand)) => { (ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(victim_cand)) => {
// Prefer these to a global where-clause bound // Prefer these to a global where-clause bound
// (see issue #50825). // (see issue #50825).
if is_global(victim_cand) { DropVictim::Yes } else { DropVictim::No } if is_global(*victim_cand) { DropVictim::Yes } else { DropVictim::No }
} }
( (
ImplCandidate(_) ImplCandidate(_)
@ -1957,12 +1957,12 @@ fn candidate_should_be_dropped_in_favor_of(
| TraitUpcastingUnsizeCandidate(_) | TraitUpcastingUnsizeCandidate(_)
| BuiltinCandidate { has_nested: true } | BuiltinCandidate { has_nested: true }
| TraitAliasCandidate, | TraitAliasCandidate,
ParamCandidate(ref victim_cand), ParamCandidate(victim_cand),
) => { ) => {
// Prefer these to a global where-clause bound // Prefer these to a global where-clause bound
// (see issue #50825). // (see issue #50825).
DropVictim::drop_if( DropVictim::drop_if(
is_global(victim_cand) && other.evaluation.must_apply_modulo_regions(), is_global(*victim_cand) && other.evaluation.must_apply_modulo_regions(),
) )
} }

View File

@ -132,7 +132,7 @@ fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool {
debug!(?predicates); debug!(?predicates);
let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| { let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| {
pred.instantiate_supertrait(tcx, &trait_ref) pred.instantiate_supertrait(tcx, trait_ref)
.as_trait_clause() .as_trait_clause()
.map(|trait_ref| item.clone_and_push(trait_ref.map_bound(|t| t.trait_ref), *span)) .map(|trait_ref| item.clone_and_push(trait_ref.map_bound(|t| t.trait_ref), *span))
}); });

View File

@ -125,7 +125,7 @@ fn prepare_vtable_segments_inner<'tcx, T>(
.predicates .predicates
.into_iter() .into_iter()
.filter_map(move |(pred, _)| { .filter_map(move |(pred, _)| {
pred.instantiate_supertrait(tcx, &inner_most_trait_ref).as_trait_clause() pred.instantiate_supertrait(tcx, inner_most_trait_ref).as_trait_clause()
}); });
// Find an unvisited supertrait // Find an unvisited supertrait

View File

@ -2,7 +2,7 @@ error[E0277]: the trait bound `&'static u32: Defaulted` is not satisfied
--> $DIR/typeck-default-trait-impl-precedence.rs:19:20 --> $DIR/typeck-default-trait-impl-precedence.rs:19:20
| |
LL | is_defaulted::<&'static u32>(); LL | is_defaulted::<&'static u32>();
| ^^^^^^^^^^^^ the trait `Signed` is not implemented for `&'static u32`, which is required by `&'static u32: Defaulted` | ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`, which is required by `&'static u32: Defaulted`
| |
note: required for `&'static u32` to implement `Defaulted` note: required for `&'static u32` to implement `Defaulted`
--> $DIR/typeck-default-trait-impl-precedence.rs:10:19 --> $DIR/typeck-default-trait-impl-precedence.rs:10:19

View File

@ -2,7 +2,7 @@ error[E0277]: the trait bound `i32: Baz<Self>` is not satisfied
--> $DIR/assume-gat-normalization-for-nested-goals.rs:9:30 --> $DIR/assume-gat-normalization-for-nested-goals.rs:9:30
| |
LL | type Bar<T>: Baz<Self> = i32; LL | type Bar<T>: Baz<Self> = i32;
| ^^^ the trait `Eq<i32>` is not implemented for `i32`, which is required by `i32: Baz<Self>` | ^^^ the trait `Eq<i32>` is not implemented for `<Self as Foo>::Bar<()>`, which is required by `i32: Baz<Self>`
| |
note: required for `i32` to implement `Baz<Self>` note: required for `i32` to implement `Baz<Self>`
--> $DIR/assume-gat-normalization-for-nested-goals.rs:16:23 --> $DIR/assume-gat-normalization-for-nested-goals.rs:16:23

View File

@ -46,7 +46,7 @@ error[E0277]: the trait bound `impl Into<u32>: Into<impl Debug>` is not satisfie
--> $DIR/nested_impl_trait.rs:6:46 --> $DIR/nested_impl_trait.rs:6:46
| |
LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x } LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
| ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Into<u32>`, which is required by `impl Into<u32>: Into<impl Debug>` | ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`, which is required by `impl Into<u32>: Into<impl Debug>`
| |
= help: the trait `Into<U>` is implemented for `T` = help: the trait `Into<U>` is implemented for `T`
= note: required for `impl Into<u32>` to implement `Into<impl Debug>` = note: required for `impl Into<u32>` to implement `Into<impl Debug>`
@ -55,7 +55,7 @@ error[E0277]: the trait bound `impl Into<u32>: Into<impl Debug>` is not satisfie
--> $DIR/nested_impl_trait.rs:19:34 --> $DIR/nested_impl_trait.rs:19:34
| |
LL | fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x } LL | fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
| ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Into<u32>`, which is required by `impl Into<u32>: Into<impl Debug>` | ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`, which is required by `impl Into<u32>: Into<impl Debug>`
| |
= help: the trait `Into<U>` is implemented for `T` = help: the trait `Into<U>` is implemented for `T`
= note: required for `impl Into<u32>` to implement `Into<impl Debug>` = note: required for `impl Into<u32>` to implement `Into<impl Debug>`

View File

@ -4,7 +4,7 @@ error[E0277]: `&'static (dyn Dummy + 'static)` cannot be sent between threads sa
LL | assert_send::<&'static (dyn Dummy + 'static)>(); LL | assert_send::<&'static (dyn Dummy + 'static)>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely
| |
= help: the trait `Sync` is not implemented for `&'static (dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send` = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send`
= note: required for `&'static (dyn Dummy + 'static)` to implement `Send` = note: required for `&'static (dyn Dummy + 'static)` to implement `Send`
note: required by a bound in `assert_send` note: required by a bound in `assert_send`
--> $DIR/kindck-send-object.rs:5:18 --> $DIR/kindck-send-object.rs:5:18

View File

@ -4,7 +4,7 @@ error[E0277]: `&'a (dyn Dummy + 'a)` cannot be sent between threads safely
LL | assert_send::<&'a dyn Dummy>(); LL | assert_send::<&'a dyn Dummy>();
| ^^^^^^^^^^^^^ `&'a (dyn Dummy + 'a)` cannot be sent between threads safely | ^^^^^^^^^^^^^ `&'a (dyn Dummy + 'a)` cannot be sent between threads safely
| |
= help: the trait `Sync` is not implemented for `&'a (dyn Dummy + 'a)`, which is required by `&'a (dyn Dummy + 'a): Send` = help: the trait `Sync` is not implemented for `(dyn Dummy + 'a)`, which is required by `&'a (dyn Dummy + 'a): Send`
= note: required for `&'a (dyn Dummy + 'a)` to implement `Send` = note: required for `&'a (dyn Dummy + 'a)` to implement `Send`
note: required by a bound in `assert_send` note: required by a bound in `assert_send`
--> $DIR/kindck-send-object1.rs:5:18 --> $DIR/kindck-send-object1.rs:5:18

View File

@ -4,7 +4,7 @@ error[E0277]: `&'static (dyn Dummy + 'static)` cannot be sent between threads sa
LL | assert_send::<&'static dyn Dummy>(); LL | assert_send::<&'static dyn Dummy>();
| ^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely | ^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely
| |
= help: the trait `Sync` is not implemented for `&'static (dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send` = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send`
= note: required for `&'static (dyn Dummy + 'static)` to implement `Send` = note: required for `&'static (dyn Dummy + 'static)` to implement `Send`
note: required by a bound in `assert_send` note: required by a bound in `assert_send`
--> $DIR/kindck-send-object2.rs:3:18 --> $DIR/kindck-send-object2.rs:3:18

View File

@ -4,7 +4,7 @@ error[E0277]: `&mut &mut &mut &mut Vec<i32>` is not an iterator
LL | for _ in &mut &mut v {} LL | for _ in &mut &mut v {}
| ^^^^^^^^^^^ `&mut &mut &mut &mut Vec<i32>` is not an iterator | ^^^^^^^^^^^ `&mut &mut &mut &mut Vec<i32>` is not an iterator
| |
= help: the trait `Iterator` is not implemented for `&mut &mut &mut &mut Vec<i32>`, which is required by `&mut &mut &mut &mut Vec<i32>: IntoIterator` = help: the trait `Iterator` is not implemented for `Vec<i32>`, which is required by `&mut &mut &mut &mut Vec<i32>: IntoIterator`
= note: required for `&mut Vec<i32>` to implement `Iterator` = note: required for `&mut Vec<i32>` to implement `Iterator`
= note: 3 redundant requirements hidden = note: 3 redundant requirements hidden
= note: required for `&mut &mut &mut &mut Vec<i32>` to implement `Iterator` = note: required for `&mut &mut &mut &mut Vec<i32>` to implement `Iterator`
@ -21,7 +21,7 @@ error[E0277]: `&mut &mut &mut [u8; 1]` is not an iterator
LL | for _ in &mut v {} LL | for _ in &mut v {}
| ^^^^^^ `&mut &mut &mut [u8; 1]` is not an iterator | ^^^^^^ `&mut &mut &mut [u8; 1]` is not an iterator
| |
= help: the trait `Iterator` is not implemented for `&mut &mut &mut [u8; 1]`, which is required by `&mut &mut &mut [u8; 1]: IntoIterator` = help: the trait `Iterator` is not implemented for `[u8; 1]`, which is required by `&mut &mut &mut [u8; 1]: IntoIterator`
= note: required for `&mut [u8; 1]` to implement `Iterator` = note: required for `&mut [u8; 1]` to implement `Iterator`
= note: 2 redundant requirements hidden = note: 2 redundant requirements hidden
= note: required for `&mut &mut &mut [u8; 1]` to implement `Iterator` = note: required for `&mut &mut &mut [u8; 1]` to implement `Iterator`

View File

@ -4,7 +4,7 @@ error: future cannot be sent between threads safely
LL | is_send(foo()); LL | is_send(foo());
| ^^^^^ future returned by `foo` is not `Send` | ^^^^^ future returned by `foo` is not `Send`
| |
= help: the trait `Sync` is not implemented for `impl Future<Output = ()>`, which is required by `impl Future<Output = ()>: Send` = help: the trait `Sync` is not implemented for `NotSync`, which is required by `impl Future<Output = ()>: Send`
note: future is not `Send` as this value is used across an await note: future is not `Send` as this value is used across an await
--> $DIR/auto-with-drop_tracking_mir.rs:16:11 --> $DIR/auto-with-drop_tracking_mir.rs:16:11
| |

View File

@ -4,6 +4,11 @@ error[E0277]: the trait bound `(): Foo` is not satisfied
LL | needs_foo::<()>(); LL | needs_foo::<()>();
| ^^ the trait `Bar` is not implemented for `()`, which is required by `(): Foo` | ^^ the trait `Bar` is not implemented for `()`, which is required by `(): Foo`
| |
help: this trait has no implementations, consider adding one
--> $DIR/point-at-failing-nested.rs:4:1
|
LL | trait Bar {}
| ^^^^^^^^^
note: required for `()` to implement `Foo` note: required for `()` to implement `Foo`
--> $DIR/point-at-failing-nested.rs:9:12 --> $DIR/point-at-failing-nested.rs:9:12
| |

View File

@ -6,6 +6,11 @@ LL | needs_foo(());
| | | |
| required by a bound introduced by this call | required by a bound introduced by this call
| |
help: this trait has no implementations, consider adding one
--> $DIR/where-clause-doesnt-apply.rs:2:1
|
LL | trait Bar {}
| ^^^^^^^^^
note: required for `()` to implement `Foo` note: required for `()` to implement `Foo`
--> $DIR/where-clause-doesnt-apply.rs:4:9 --> $DIR/where-clause-doesnt-apply.rs:4:9
| |

View File

@ -2,7 +2,7 @@ error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied
--> $DIR/root-obligation.rs:6:38 --> $DIR/root-obligation.rs:6:38
| |
LL | .filter(|c| "aeiou".contains(c)) LL | .filter(|c| "aeiou".contains(c))
| -------- ^ the trait `Fn(char)` is not implemented for `&char`, which is required by `&char: Pattern<'_>` | -------- ^ the trait `Fn(char)` is not implemented for `char`, which is required by `&char: Pattern<'_>`
| | | |
| required by a bound introduced by this call | required by a bound introduced by this call
| |

View File

@ -2,7 +2,7 @@ error[E0277]: `&u8` cannot be safely transmuted into `&UnsafeCell<u8>`
--> $DIR/unsafecell.rs:27:50 --> $DIR/unsafecell.rs:27:50
| |
LL | assert::is_maybe_transmutable::<&'static u8, &'static UnsafeCell<u8>>(); LL | assert::is_maybe_transmutable::<&'static u8, &'static UnsafeCell<u8>>();
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Freeze` is not implemented for `&'static UnsafeCell<u8>` | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Freeze` is not implemented for `UnsafeCell<u8>`
| |
note: required by a bound in `is_maybe_transmutable` note: required by a bound in `is_maybe_transmutable`
--> $DIR/unsafecell.rs:12:14 --> $DIR/unsafecell.rs:12:14
@ -17,7 +17,7 @@ error[E0277]: `&UnsafeCell<u8>` cannot be safely transmuted into `&UnsafeCell<u8
--> $DIR/unsafecell.rs:29:62 --> $DIR/unsafecell.rs:29:62
| |
LL | assert::is_maybe_transmutable::<&'static UnsafeCell<u8>, &'static UnsafeCell<u8>>(); LL | assert::is_maybe_transmutable::<&'static UnsafeCell<u8>, &'static UnsafeCell<u8>>();
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Freeze` is not implemented for `&'static UnsafeCell<u8>` | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Freeze` is not implemented for `UnsafeCell<u8>`
| |
note: required by a bound in `is_maybe_transmutable` note: required by a bound in `is_maybe_transmutable`
--> $DIR/unsafecell.rs:12:14 --> $DIR/unsafecell.rs:12:14

View File

@ -0,0 +1,16 @@
trait Foo<'s> {}
impl<'s> Foo<'s> for () {}
struct Bar;
impl<'s, T: Foo<'s>> From<T> for Bar {
fn from(_: T) -> Self {
Bar
}
}
fn main() {
let _: Bar = ((),).into();
//~^ ERROR he trait bound `((),): Into<Bar>` is not satisfied
}

View File

@ -0,0 +1,20 @@
error[E0277]: the trait bound `((),): Into<Bar>` is not satisfied
--> $DIR/suggest-similar-impls-for-root-obligation.rs:14:24
|
LL | let _: Bar = ((),).into();
| ^^^^ the trait `Foo<'_>` is not implemented for `((),)`, which is required by `((),): Into<_>`
|
= help: the trait `Foo<'_>` is implemented for `()`
= help: for that trait implementation, expected `()`, found `((),)`
note: required for `Bar` to implement `From<((),)>`
--> $DIR/suggest-similar-impls-for-root-obligation.rs:7:22
|
LL | impl<'s, T: Foo<'s>> From<T> for Bar {
| ------- ^^^^^^^ ^^^
| |
| unsatisfied trait bound introduced here
= note: required for `((),)` to implement `Into<Bar>`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.