diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index b7ccfac8063d7..1123cab807651 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -402,7 +402,7 @@ impl ObligationCauseCode<'_> { // `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(ObligationCauseCode<'_>, 40); +static_assert_size!(ObligationCauseCode<'_>, 48); #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum StatementAsExpression { @@ -440,11 +440,11 @@ pub struct IfExpressionCause { #[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)] pub struct DerivedObligationCause<'tcx> { - /// The trait reference of the parent obligation that led to the + /// The trait predicate of the parent obligation that led to the /// current obligation. Note that only trait obligations lead to - /// derived obligations, so we just store the trait reference here + /// derived obligations, so we just store the trait predicate here /// directly. - pub parent_trait_ref: ty::PolyTraitRef<'tcx>, + pub parent_trait_pred: ty::PolyTraitPredicate<'tcx>, /// The parent trait had this cause. pub parent_code: Lrc>, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 64c00c353ca1b..6174c922e2d06 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -766,6 +766,17 @@ impl<'tcx> TraitPredicate<'tcx> { *param_env = param_env.with_constness(self.constness.and(param_env.constness())) } } + + /// Remap the constness of this predicate before emitting it for diagnostics. + pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) { + // this is different to `remap_constness` that callees want to print this predicate + // in case of selection errors. `T: ~const Drop` bounds cannot end up here when the + // param_env is not const because we it is always satisfied in non-const contexts. + if let hir::Constness::NotConst = param_env.constness() { + self.constness = ty::BoundConstness::NotConst; + } + } + pub fn def_id(self) -> DefId { self.trait_ref.def_id } @@ -784,6 +795,14 @@ impl<'tcx> PolyTraitPredicate<'tcx> { pub fn self_ty(self) -> ty::Binder<'tcx, Ty<'tcx>> { self.map_bound(|trait_ref| trait_ref.self_ty()) } + + /// Remap the constness of this predicate before emitting it for diagnostics. + pub fn remap_constness_diag(&mut self, param_env: ParamEnv<'tcx>) { + *self = self.map_bound(|mut p| { + p.remap_constness_diag(param_env); + p + }); + } } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)] diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index bbdaf248a9e72..952a7513f1052 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2413,6 +2413,29 @@ impl<'tcx> ty::Binder<'tcx, ty::TraitRef<'tcx>> { } } +#[derive(Copy, Clone, TypeFoldable, Lift)] +pub struct TraitPredPrintModifiersAndPath<'tcx>(ty::TraitPredicate<'tcx>); + +impl<'tcx> fmt::Debug for TraitPredPrintModifiersAndPath<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + +impl<'tcx> ty::TraitPredicate<'tcx> { + pub fn print_modifiers_and_trait_path(self) -> TraitPredPrintModifiersAndPath<'tcx> { + TraitPredPrintModifiersAndPath(self) + } +} + +impl<'tcx> ty::PolyTraitPredicate<'tcx> { + pub fn print_modifiers_and_trait_path( + self, + ) -> ty::Binder<'tcx, TraitPredPrintModifiersAndPath<'tcx>> { + self.map_bound(TraitPredPrintModifiersAndPath) + } +} + forward_display_to_print! { Ty<'tcx>, &'tcx ty::List>>, @@ -2427,6 +2450,7 @@ forward_display_to_print! { ty::Binder<'tcx, TraitRefPrintOnlyTraitName<'tcx>>, ty::Binder<'tcx, ty::FnSig<'tcx>>, ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, + ty::Binder<'tcx, TraitPredPrintModifiersAndPath<'tcx>>, ty::Binder<'tcx, ty::SubtypePredicate<'tcx>>, ty::Binder<'tcx, ty::ProjectionPredicate<'tcx>>, ty::Binder<'tcx, ty::OutlivesPredicate, ty::Region<'tcx>>>, @@ -2491,6 +2515,18 @@ define_print_and_forward_display! { p!(print_def_path(self.0.def_id, &[])); } + TraitPredPrintModifiersAndPath<'tcx> { + if let ty::BoundConstness::ConstIfConst = self.0.constness { + p!("~const ") + } + + if let ty::ImplPolarity::Negative = self.0.polarity { + p!("!") + } + + p!(print(self.0.trait_ref.print_only_trait_path())); + } + ty::ParamTy { p!(write("{}", self.name)) } @@ -2508,8 +2544,11 @@ define_print_and_forward_display! { } ty::TraitPredicate<'tcx> { - p!(print(self.trait_ref.self_ty()), ": ", - print(self.trait_ref.print_only_trait_path())) + p!(print(self.trait_ref.self_ty()), ": "); + if let ty::BoundConstness::ConstIfConst = self.constness { + p!("~const "); + } + p!(print(self.trait_ref.print_only_trait_path())) } ty::ProjectionPredicate<'tcx> { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 52d52752b1583..d99bdd3bdd5be 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -321,6 +321,7 @@ symbols! { and, and_then, any, + append_const_msg, arbitrary_enum_discriminant, arbitrary_self_types, arith_offset, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 0760f62685127..213084cdcd659 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -205,6 +205,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { self.note_obligation_cause_code( &mut err, &obligation.predicate, + obligation.param_env, obligation.cause.code(), &mut vec![], &mut Default::default(), @@ -288,7 +289,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { match bound_predicate.skip_binder() { ty::PredicateKind::Trait(trait_predicate) => { let trait_predicate = bound_predicate.rebind(trait_predicate); - let trait_predicate = self.resolve_vars_if_possible(trait_predicate); + let mut trait_predicate = self.resolve_vars_if_possible(trait_predicate); + + trait_predicate.remap_constness_diag(obligation.param_env); + let predicate_is_const = ty::BoundConstness::ConstIfConst + == trait_predicate.skip_binder().constness; if self.tcx.sess.has_errors() && trait_predicate.references_error() { return; @@ -305,13 +310,18 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { }) .unwrap_or_default(); - let OnUnimplementedNote { message, label, note, enclosing_scope } = - self.on_unimplemented_note(trait_ref, &obligation); + let OnUnimplementedNote { + message, + label, + note, + enclosing_scope, + append_const_msg, + } = self.on_unimplemented_note(trait_ref, &obligation); 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_unsize = { Some(trait_ref.def_id()) == self.tcx.lang_items().unsize_trait() }; - let (message, note) = if is_try_conversion { + let (message, note, append_const_msg) = if is_try_conversion { ( Some(format!( "`?` couldn't convert the error to `{}`", @@ -322,9 +332,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { conversion on the error value using the `From` trait" .to_owned(), ), + Some(None), ) } else { - (message, note) + (message, note, append_const_msg) }; let mut err = struct_span_err!( @@ -332,11 +343,27 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { span, E0277, "{}", - message.unwrap_or_else(|| format!( - "the trait bound `{}` is not satisfied{}", - trait_ref.without_const().to_predicate(tcx), - post_message, - )) + message + .and_then(|cannot_do_this| { + match (predicate_is_const, append_const_msg) { + // do nothing if predicate is not const + (false, _) => Some(cannot_do_this), + // suggested using default post message + (true, Some(None)) => { + Some(format!("{cannot_do_this} in const contexts")) + } + // overriden post message + (true, Some(Some(post_message))) => { + Some(format!("{cannot_do_this}{post_message}")) + } + // fallback to generic message + (true, None) => None, + } + }) + .unwrap_or_else(|| format!( + "the trait bound `{}` is not satisfied{}", + trait_predicate, post_message, + )) ); if is_try_conversion { @@ -384,7 +411,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { format!( "{}the trait `{}` is not implemented for `{}`", pre_message, - trait_ref.print_only_trait_path(), + trait_predicate.print_modifiers_and_trait_path(), trait_ref.skip_binder().self_ty(), ) }; @@ -392,7 +419,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { if self.suggest_add_reference_to_arg( &obligation, &mut err, - &trait_ref, + trait_predicate, have_alt_message, ) { self.note_obligation_cause(&mut err, &obligation); @@ -435,18 +462,28 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err.span_label(enclosing_scope_span, s.as_str()); } - self.suggest_dereferences(&obligation, &mut err, trait_ref); - self.suggest_fn_call(&obligation, &mut err, trait_ref); - self.suggest_remove_reference(&obligation, &mut err, trait_ref); - self.suggest_semicolon_removal(&obligation, &mut err, span, trait_ref); + self.suggest_dereferences(&obligation, &mut err, trait_predicate); + self.suggest_fn_call(&obligation, &mut err, trait_predicate); + self.suggest_remove_reference(&obligation, &mut err, trait_predicate); + self.suggest_semicolon_removal( + &obligation, + &mut err, + span, + trait_predicate, + ); self.note_version_mismatch(&mut err, &trait_ref); self.suggest_remove_await(&obligation, &mut err); if Some(trait_ref.def_id()) == tcx.lang_items().try_trait() { - self.suggest_await_before_try(&mut err, &obligation, trait_ref, span); + self.suggest_await_before_try( + &mut err, + &obligation, + trait_predicate, + span, + ); } - if self.suggest_impl_trait(&mut err, span, &obligation, trait_ref) { + if self.suggest_impl_trait(&mut err, span, &obligation, trait_predicate) { err.emit(); return; } @@ -494,7 +531,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // which is somewhat confusing. self.suggest_restricting_param_bound( &mut err, - trait_ref, + trait_predicate, obligation.cause.body_id, ); } else if !have_alt_message { @@ -506,7 +543,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // Changing mutability doesn't make a difference to whether we have // an `Unsize` impl (Fixes ICE in #71036) if !is_unsize { - self.suggest_change_mut(&obligation, &mut err, trait_ref); + self.suggest_change_mut(&obligation, &mut err, trait_predicate); } // If this error is due to `!: Trait` not implemented but `(): Trait` is @@ -1121,7 +1158,7 @@ trait InferCtxtPrivExt<'hir, 'tcx> { fn mk_trait_obligation_with_new_self_ty( &self, param_env: ty::ParamEnv<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, + trait_ref: ty::PolyTraitPredicate<'tcx>, new_self_ty: Ty<'tcx>, ) -> PredicateObligation<'tcx>; @@ -1540,7 +1577,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { ) -> Option<(String, Option)> { match code { ObligationCauseCode::BuiltinDerivedObligation(data) => { - let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_ref); + let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred); match self.get_parent_trait_ref(&data.parent_code) { Some(t) => Some(t), None => { @@ -1593,21 +1630,20 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { fn mk_trait_obligation_with_new_self_ty( &self, param_env: ty::ParamEnv<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, + trait_ref: ty::PolyTraitPredicate<'tcx>, new_self_ty: Ty<'tcx>, ) -> PredicateObligation<'tcx> { assert!(!new_self_ty.has_escaping_bound_vars()); - let trait_ref = trait_ref.map_bound_ref(|tr| ty::TraitRef { - substs: self.tcx.mk_substs_trait(new_self_ty, &tr.substs[1..]), + let trait_pred = trait_ref.map_bound_ref(|tr| ty::TraitPredicate { + trait_ref: ty::TraitRef { + substs: self.tcx.mk_substs_trait(new_self_ty, &tr.trait_ref.substs[1..]), + ..tr.trait_ref + }, ..*tr }); - Obligation::new( - ObligationCause::dummy(), - param_env, - trait_ref.without_const().to_predicate(self.tcx), - ) + Obligation::new(ObligationCause::dummy(), param_env, trait_pred.to_predicate(self.tcx)) } #[instrument(skip(self), level = "debug")] @@ -2008,6 +2044,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { self.note_obligation_cause_code( err, &obligation.predicate, + obligation.param_env, obligation.cause.code(), &mut vec![], &mut Default::default(), @@ -2155,7 +2192,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { cause_code: &ObligationCauseCode<'tcx>, ) -> bool { if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code { - let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_ref); + let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred); let self_ty = parent_trait_ref.skip_binder().self_ty(); if obligated_types.iter().any(|ot| ot == &self_ty) { return true; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 3fb42a2ec4a1d..8b92c7aa05108 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -48,7 +48,7 @@ pub trait InferCtxtExt<'tcx> { fn suggest_restricting_param_bound( &self, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::PolyTraitRef<'tcx>, + trait_pred: ty::PolyTraitPredicate<'tcx>, body_id: hir::HirId, ); @@ -56,7 +56,7 @@ pub trait InferCtxtExt<'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, + trait_pred: ty::PolyTraitPredicate<'tcx>, ); fn get_closure_name( @@ -70,14 +70,14 @@ pub trait InferCtxtExt<'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, + trait_pred: ty::PolyTraitPredicate<'tcx>, ); fn suggest_add_reference_to_arg( &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>, + trait_pred: ty::PolyTraitPredicate<'tcx>, has_custom_message: bool, ) -> bool; @@ -85,7 +85,7 @@ pub trait InferCtxtExt<'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, + trait_pred: ty::PolyTraitPredicate<'tcx>, ); fn suggest_remove_await( @@ -98,7 +98,7 @@ pub trait InferCtxtExt<'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, + trait_pred: ty::PolyTraitPredicate<'tcx>, ); fn suggest_semicolon_removal( @@ -106,7 +106,7 @@ pub trait InferCtxtExt<'tcx> { obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, span: Span, - trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, + trait_pred: ty::PolyTraitPredicate<'tcx>, ); fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option; @@ -116,7 +116,7 @@ pub trait InferCtxtExt<'tcx> { err: &mut DiagnosticBuilder<'_>, span: Span, obligation: &PredicateObligation<'tcx>, - trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, + trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> bool; fn point_at_returns_when_relevant( @@ -154,7 +154,7 @@ pub trait InferCtxtExt<'tcx> { interior_extra_info: Option<(Option, Span, Option, Option)>, inner_generator_body: Option<&hir::Body<'tcx>>, outer_generator: Option, - trait_ref: ty::TraitRef<'tcx>, + trait_pred: ty::TraitPredicate<'tcx>, target_ty: Ty<'tcx>, typeck_results: Option<&ty::TypeckResults<'tcx>>, obligation: &PredicateObligation<'tcx>, @@ -165,6 +165,7 @@ pub trait InferCtxtExt<'tcx> { &self, err: &mut DiagnosticBuilder<'_>, predicate: &T, + param_env: ty::ParamEnv<'tcx>, cause_code: &ObligationCauseCode<'tcx>, obligated_types: &mut Vec<&ty::TyS<'tcx>>, seen_requirements: &mut FxHashSet, @@ -178,7 +179,7 @@ pub trait InferCtxtExt<'tcx> { &self, err: &mut DiagnosticBuilder<'_>, obligation: &PredicateObligation<'tcx>, - trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, + trait_pred: ty::PolyTraitPredicate<'tcx>, span: Span, ); } @@ -204,7 +205,7 @@ fn suggest_restriction<'tcx>( err: &mut DiagnosticBuilder<'_>, fn_sig: Option<&hir::FnSig<'_>>, projection: Option<&ty::ProjectionTy<'_>>, - trait_ref: ty::PolyTraitRef<'tcx>, + trait_pred: ty::PolyTraitPredicate<'tcx>, super_traits: Option<(&Ident, &hir::GenericBounds<'_>)>, ) { // When we are dealing with a trait, `super_traits` will be `Some`: @@ -257,9 +258,9 @@ fn suggest_restriction<'tcx>( // The type param `T: Trait` we will suggest to introduce. let type_param = format!("{}: {}", type_param_name, bound_str); - // FIXME: modify the `trait_ref` instead of string shenanigans. + // FIXME: modify the `trait_pred` instead of string shenanigans. // Turn `::Bar: Qux` into `::Bar: Qux`. - let pred = trait_ref.without_const().to_predicate(tcx).to_string(); + let pred = trait_pred.to_predicate(tcx).to_string(); let pred = pred.replace(&impl_trait_str, &type_param_name); let mut sugg = vec![ // Find the last of the generic parameters contained within the span of @@ -301,19 +302,19 @@ fn suggest_restriction<'tcx>( .find(|p| !matches!(p.kind, hir::GenericParamKind::Type { synthetic: true, .. })), super_traits, ) { - (_, None) => predicate_constraint( - generics, - trait_ref.without_const().to_predicate(tcx).to_string(), + (_, None) => predicate_constraint(generics, trait_pred.to_predicate(tcx).to_string()), + (None, Some((ident, []))) => ( + ident.span.shrink_to_hi(), + format!(": {}", trait_pred.print_modifiers_and_trait_path()), + ), + (_, Some((_, [.., bounds]))) => ( + bounds.span().shrink_to_hi(), + format!(" + {}", trait_pred.print_modifiers_and_trait_path()), + ), + (Some(_), Some((_, []))) => ( + generics.span.shrink_to_hi(), + format!(": {}", trait_pred.print_modifiers_and_trait_path()), ), - (None, Some((ident, []))) => { - (ident.span.shrink_to_hi(), format!(": {}", trait_ref.print_only_trait_path())) - } - (_, Some((_, [.., bounds]))) => { - (bounds.span().shrink_to_hi(), format!(" + {}", trait_ref.print_only_trait_path())) - } - (Some(_), Some((_, []))) => { - (generics.span.shrink_to_hi(), format!(": {}", trait_ref.print_only_trait_path())) - } }; err.span_suggestion_verbose( @@ -329,10 +330,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { fn suggest_restricting_param_bound( &self, mut err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::PolyTraitRef<'tcx>, + trait_pred: ty::PolyTraitPredicate<'tcx>, body_id: hir::HirId, ) { - let self_ty = trait_ref.skip_binder().self_ty(); + let self_ty = trait_pred.skip_binder().self_ty(); let (param_ty, projection) = match self_ty.kind() { ty::Param(_) => (true, None), ty::Projection(projection) => (false, Some(projection)), @@ -358,7 +359,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err, None, projection, - trait_ref, + trait_pred, Some((ident, bounds)), ); return; @@ -372,7 +373,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { assert!(param_ty); // Restricting `Self` for a single method. suggest_restriction( - self.tcx, &generics, "`Self`", err, None, projection, trait_ref, None, + self.tcx, &generics, "`Self`", err, None, projection, trait_pred, None, ); return; } @@ -398,7 +399,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err, Some(fn_sig), projection, - trait_ref, + trait_pred, None, ); return; @@ -417,7 +418,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err, None, projection, - trait_ref, + trait_pred, None, ); return; @@ -442,15 +443,16 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { { // Missing generic type parameter bound. let param_name = self_ty.to_string(); - let constraint = - with_no_trimmed_paths(|| trait_ref.print_only_trait_path().to_string()); + let constraint = with_no_trimmed_paths(|| { + trait_pred.print_modifiers_and_trait_path().to_string() + }); if suggest_constraining_type_param( self.tcx, generics, &mut err, ¶m_name, &constraint, - Some(trait_ref.def_id()), + Some(trait_pred.def_id()), ) { return; } @@ -471,7 +473,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { }) if !param_ty => { // Missing generic type parameter bound. let param_name = self_ty.to_string(); - let constraint = trait_ref.print_only_trait_path().to_string(); + let constraint = trait_pred.print_modifiers_and_trait_path().to_string(); if suggest_arbitrary_trait_bound(generics, &mut err, ¶m_name, &constraint) { return; } @@ -492,7 +494,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, + trait_pred: ty::PolyTraitPredicate<'tcx>, ) { // It only make sense when suggesting dereferences for arguments let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } = @@ -505,13 +507,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let param_env = obligation.param_env; let body_id = obligation.cause.body_id; let span = obligation.cause.span; - let real_trait_ref = match &*code { + let real_trait_pred = match &*code { ObligationCauseCode::ImplDerivedObligation(cause) | ObligationCauseCode::DerivedObligation(cause) - | ObligationCauseCode::BuiltinDerivedObligation(cause) => cause.parent_trait_ref, - _ => trait_ref, + | ObligationCauseCode::BuiltinDerivedObligation(cause) => cause.parent_trait_pred, + _ => trait_pred, }; - let real_ty = match real_trait_ref.self_ty().no_bound_vars() { + let real_ty = match real_trait_pred.self_ty().no_bound_vars() { Some(ty) => ty, None => return, }; @@ -522,7 +524,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // Re-add the `&` let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl }); let obligation = - self.mk_trait_obligation_with_new_self_ty(param_env, real_trait_ref, ty); + self.mk_trait_obligation_with_new_self_ty(param_env, real_trait_pred, ty); Some(steps).filter(|_| self.predicate_may_hold(&obligation)) }) { if steps > 0 { @@ -589,9 +591,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, + trait_pred: ty::PolyTraitPredicate<'tcx>, ) { - let self_ty = match trait_ref.self_ty().no_bound_vars() { + let self_ty = match trait_pred.self_ty().no_bound_vars() { None => return, Some(ty) => ty, }; @@ -611,7 +613,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { }; let new_obligation = - self.mk_trait_obligation_with_new_self_ty(obligation.param_env, trait_ref, output_ty); + self.mk_trait_obligation_with_new_self_ty(obligation.param_env, trait_pred, output_ty); match self.evaluate_obligation(&new_obligation) { Ok( @@ -682,7 +684,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - poly_trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>, + poly_trait_pred: ty::PolyTraitPredicate<'tcx>, has_custom_message: bool, ) -> bool { let span = obligation.cause.span; @@ -715,24 +717,18 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let param_env = obligation.param_env; // Try to apply the original trait binding obligation by borrowing. - let mut try_borrowing = |old_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, + let mut try_borrowing = |old_pred: ty::PolyTraitPredicate<'tcx>, blacklist: &[DefId]| -> bool { - if blacklist.contains(&old_ref.def_id()) { + if blacklist.contains(&old_pred.def_id()) { return false; } - let orig_ty = old_ref.self_ty().skip_binder(); + let orig_ty = old_pred.self_ty().skip_binder(); let mk_result = |new_ty| { - let new_ref = old_ref.rebind(ty::TraitRef::new( - old_ref.def_id(), - self.tcx.mk_substs_trait(new_ty, &old_ref.skip_binder().substs[1..]), - )); - self.predicate_must_hold_modulo_regions(&Obligation::new( - ObligationCause::dummy(), - param_env, - new_ref.without_const().to_predicate(self.tcx), - )) + let obligation = + self.mk_trait_obligation_with_new_self_ty(param_env, old_pred, new_ty); + self.predicate_must_hold_modulo_regions(&obligation) }; let imm_result = mk_result(self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, orig_ty)); let mut_result = mk_result(self.tcx.mk_mut_ref(self.tcx.lifetimes.re_static, orig_ty)); @@ -748,7 +744,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let msg = format!( "the trait bound `{}: {}` is not satisfied", orig_ty, - old_ref.print_only_trait_path(), + old_pred.print_modifiers_and_trait_path(), ); if has_custom_message { err.note(&msg); @@ -764,7 +760,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { span, &format!( "expected an implementor of trait `{}`", - old_ref.print_only_trait_path(), + old_pred.print_modifiers_and_trait_path(), ), ); @@ -806,11 +802,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { }; if let ObligationCauseCode::ImplDerivedObligation(obligation) = code { - try_borrowing(obligation.parent_trait_ref, &[]) + try_borrowing(obligation.parent_trait_pred, &[]) } else if let ObligationCauseCode::BindingObligation(_, _) | ObligationCauseCode::ItemObligation(_) = code { - try_borrowing(*poly_trait_ref, &never_suggest_borrow) + try_borrowing(poly_trait_pred, &never_suggest_borrow) } else { false } @@ -822,7 +818,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, + trait_pred: ty::PolyTraitPredicate<'tcx>, ) { let span = obligation.cause.span; @@ -834,7 +830,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { return; } - let mut suggested_ty = match trait_ref.self_ty().no_bound_vars() { + let mut suggested_ty = match trait_pred.self_ty().no_bound_vars() { Some(ty) => ty, None => return, }; @@ -847,7 +843,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let new_obligation = self.mk_trait_obligation_with_new_self_ty( obligation.param_env, - trait_ref, + trait_pred, suggested_ty, ); @@ -941,7 +937,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, - trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, + trait_pred: ty::PolyTraitPredicate<'tcx>, ) { let points_at_arg = matches!( obligation.cause.code(), @@ -956,14 +952,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // Do not suggest removal of borrow from type arguments. return; } - let trait_ref = self.resolve_vars_if_possible(trait_ref); - if trait_ref.has_infer_types_or_consts() { + let trait_pred = self.resolve_vars_if_possible(trait_pred); + if trait_pred.has_infer_types_or_consts() { // Do not ICE while trying to find if a reborrow would succeed on a trait with // unresolved bindings. return; } - if let ty::Ref(region, t_type, mutability) = *trait_ref.skip_binder().self_ty().kind() { + if let ty::Ref(region, t_type, mutability) = *trait_pred.skip_binder().self_ty().kind() + { if region.is_late_bound() || t_type.has_escaping_bound_vars() { // Avoid debug assertion in `mk_obligation_for_def_id`. // @@ -980,7 +977,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let new_obligation = self.mk_trait_obligation_with_new_self_ty( obligation.param_env, - trait_ref, + trait_pred, suggested_ty, ); let suggested_ty_would_satisfy_obligation = self @@ -1002,9 +999,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } else { err.note(&format!( "`{}` is implemented for `{:?}`, but not for `{:?}`", - trait_ref.print_only_trait_path(), + trait_pred.print_modifiers_and_trait_path(), suggested_ty, - trait_ref.skip_binder().self_ty(), + trait_pred.skip_binder().self_ty(), )); } } @@ -1017,7 +1014,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, span: Span, - trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, + trait_pred: ty::PolyTraitPredicate<'tcx>, ) { let is_empty_tuple = |ty: ty::Binder<'tcx, Ty<'_>>| *ty.skip_binder().kind() == ty::Tuple(ty::List::empty()); @@ -1033,7 +1030,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { if let hir::ExprKind::Block(blk, _) = &body.value.kind { if sig.decl.output.span().overlaps(span) && blk.expr.is_none() - && is_empty_tuple(trait_ref.self_ty()) + && is_empty_tuple(trait_pred.self_ty()) { // FIXME(estebank): When encountering a method with a trait // bound not satisfied in the return type with a body that has @@ -1069,7 +1066,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err: &mut DiagnosticBuilder<'_>, span: Span, obligation: &PredicateObligation<'tcx>, - trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, + trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> bool { match obligation.cause.code().peel_derives() { // Only suggest `impl Trait` if the return type is unsized because it is `dyn Trait`. @@ -1088,8 +1085,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { return false; }; let body = hir.body(*body_id); - let trait_ref = self.resolve_vars_if_possible(trait_ref); - let ty = trait_ref.skip_binder().self_ty(); + let trait_pred = self.resolve_vars_if_possible(trait_pred); + let ty = trait_pred.skip_binder().self_ty(); let is_object_safe = match ty.kind() { ty::Dynamic(predicates, _) => { // If the `dyn Trait` is not object safe, do not suggest `Box`. @@ -1326,9 +1323,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { trait_ref.rebind(sig).to_string() } - let argument_kind = match expected_ref.skip_binder().substs.type_at(0) { - t if t.is_closure() => "closure", - t if t.is_generator() => "generator", + let argument_kind = match expected_ref.skip_binder().self_ty().kind() { + ty::Closure(..) => "closure", + ty::Generator(..) => "generator", _ => "function", }; let mut err = struct_span_err!( @@ -1455,7 +1452,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // bound was introduced. At least one generator should be present for this diagnostic to be // modified. let (mut trait_ref, mut target_ty) = match obligation.predicate.kind().skip_binder() { - ty::PredicateKind::Trait(p) => (Some(p.trait_ref), Some(p.self_ty())), + ty::PredicateKind::Trait(p) => (Some(p), Some(p.self_ty())), _ => (None, None), }; let mut generator = None; @@ -1473,11 +1470,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ObligationCauseCode::DerivedObligation(derived_obligation) | ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) | ObligationCauseCode::ImplDerivedObligation(derived_obligation) => { - let ty = derived_obligation.parent_trait_ref.skip_binder().self_ty(); + let ty = derived_obligation.parent_trait_pred.skip_binder().self_ty(); debug!( "maybe_note_obligation_cause_for_async_await: \ parent_trait_ref={:?} self_ty.kind={:?}", - derived_obligation.parent_trait_ref, + derived_obligation.parent_trait_pred, ty.kind() ); @@ -1495,7 +1492,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { seen_upvar_tys_infer_tuple = true; } _ if generator.is_none() => { - trait_ref = Some(derived_obligation.parent_trait_ref.skip_binder()); + trait_ref = Some(derived_obligation.parent_trait_pred.skip_binder()); target_ty = Some(ty); } _ => {} @@ -1651,7 +1648,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { interior_extra_info: Option<(Option, Span, Option, Option)>, inner_generator_body: Option<&hir::Body<'tcx>>, outer_generator: Option, - trait_ref: ty::TraitRef<'tcx>, + trait_pred: ty::TraitPredicate<'tcx>, target_ty: Ty<'tcx>, typeck_results: Option<&ty::TypeckResults<'tcx>>, obligation: &PredicateObligation<'tcx>, @@ -1671,7 +1668,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // not implemented. let hir = self.tcx.hir(); let trait_explanation = if let Some(name @ (sym::Send | sym::Sync)) = - self.tcx.get_diagnostic_name(trait_ref.def_id) + self.tcx.get_diagnostic_name(trait_pred.def_id()) { let (trait_name, trait_verb) = if name == sym::Send { ("`Send`", "sent") } else { ("`Sync`", "shared") }; @@ -1713,7 +1710,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { format!("is not {}", trait_name) } else { - format!("does not implement `{}`", trait_ref.print_only_trait_path()) + format!("does not implement `{}`", trait_pred.print_modifiers_and_trait_path()) }; let mut explain_yield = |interior_span: Span, @@ -1894,6 +1891,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { self.note_obligation_cause_code( err, &obligation.predicate, + obligation.param_env, next_code.unwrap(), &mut Vec::new(), &mut Default::default(), @@ -1904,6 +1902,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &self, err: &mut DiagnosticBuilder<'_>, predicate: &T, + param_env: ty::ParamEnv<'tcx>, cause_code: &ObligationCauseCode<'tcx>, obligated_types: &mut Vec<&ty::TyS<'tcx>>, seen_requirements: &mut FxHashSet, @@ -2134,7 +2133,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err.note("shared static variables must have a type that implements `Sync`"); } ObligationCauseCode::BuiltinDerivedObligation(ref data) => { - let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_ref); + let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred); let ty = parent_trait_ref.skip_binder().self_ty(); if parent_trait_ref.references_error() { err.cancel(); @@ -2149,7 +2148,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = *data.parent_code { - let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_ref); + let parent_trait_ref = + self.resolve_vars_if_possible(data.parent_trait_pred); let ty = parent_trait_ref.skip_binder().self_ty(); matches!(ty.kind(), ty::Generator(..)) || matches!(ty.kind(), ty::Closure(..)) @@ -2172,13 +2172,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { obligated_types.push(ty); - let parent_predicate = parent_trait_ref.without_const().to_predicate(tcx); + let parent_predicate = parent_trait_ref.to_predicate(tcx); if !self.is_recursive_obligation(obligated_types, &data.parent_code) { // #74711: avoid a stack overflow ensure_sufficient_stack(|| { self.note_obligation_cause_code( err, &parent_predicate, + param_env, &data.parent_code, obligated_types, seen_requirements, @@ -2189,6 +2190,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { self.note_obligation_cause_code( err, &parent_predicate, + param_env, &cause_code.peel_derives(), obligated_types, seen_requirements, @@ -2197,17 +2199,18 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } } ObligationCauseCode::ImplDerivedObligation(ref data) => { - let mut parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_ref); - let parent_def_id = parent_trait_ref.def_id(); + let mut parent_trait_pred = self.resolve_vars_if_possible(data.parent_trait_pred); + parent_trait_pred.remap_constness_diag(param_env); + let parent_def_id = parent_trait_pred.def_id(); let msg = format!( "required because of the requirements on the impl of `{}` for `{}`", - parent_trait_ref.print_only_trait_path(), - parent_trait_ref.skip_binder().self_ty() + parent_trait_pred.print_modifiers_and_trait_path(), + parent_trait_pred.skip_binder().self_ty() ); let mut candidates = vec![]; self.tcx.for_each_relevant_impl( parent_def_id, - parent_trait_ref.self_ty().skip_binder(), + parent_trait_pred.self_ty().skip_binder(), |impl_def_id| match self.tcx.hir().get_if_local(impl_def_id) { Some(Node::Item(hir::Item { kind: hir::ItemKind::Impl(hir::Impl { .. }), @@ -2236,21 +2239,21 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { _ => err.note(&msg), }; - let mut parent_predicate = parent_trait_ref.without_const().to_predicate(tcx); + let mut parent_predicate = parent_trait_pred.to_predicate(tcx); let mut data = data; let mut count = 0; seen_requirements.insert(parent_def_id); while let ObligationCauseCode::ImplDerivedObligation(child) = &*data.parent_code { // Skip redundant recursive obligation notes. See `ui/issue-20413.rs`. - let child_trait_ref = self.resolve_vars_if_possible(child.parent_trait_ref); - let child_def_id = child_trait_ref.def_id(); + let child_trait_pred = self.resolve_vars_if_possible(child.parent_trait_pred); + let child_def_id = child_trait_pred.def_id(); if seen_requirements.insert(child_def_id) { break; } count += 1; data = child; - parent_predicate = child_trait_ref.without_const().to_predicate(tcx); - parent_trait_ref = child_trait_ref; + parent_predicate = child_trait_pred.to_predicate(tcx); + parent_trait_pred = child_trait_pred; } if count > 0 { err.note(&format!( @@ -2260,8 +2263,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { )); err.note(&format!( "required because of the requirements on the impl of `{}` for `{}`", - parent_trait_ref.print_only_trait_path(), - parent_trait_ref.skip_binder().self_ty() + parent_trait_pred.print_modifiers_and_trait_path(), + parent_trait_pred.skip_binder().self_ty() )); } // #74711: avoid a stack overflow @@ -2269,6 +2272,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { self.note_obligation_cause_code( err, &parent_predicate, + param_env, &data.parent_code, obligated_types, seen_requirements, @@ -2276,13 +2280,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { }); } ObligationCauseCode::DerivedObligation(ref data) => { - let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_ref); - let parent_predicate = parent_trait_ref.without_const().to_predicate(tcx); + let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred); + let parent_predicate = parent_trait_ref.to_predicate(tcx); // #74711: avoid a stack overflow ensure_sufficient_stack(|| { self.note_obligation_cause_code( err, &parent_predicate, + param_env, &data.parent_code, obligated_types, seen_requirements, @@ -2336,6 +2341,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { self.note_obligation_cause_code( err, predicate, + param_env, &parent_code, obligated_types, seen_requirements, @@ -2426,15 +2432,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &self, err: &mut DiagnosticBuilder<'_>, obligation: &PredicateObligation<'tcx>, - trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, + trait_pred: ty::PolyTraitPredicate<'tcx>, span: Span, ) { debug!( - "suggest_await_before_try: obligation={:?}, span={:?}, trait_ref={:?}, trait_ref_self_ty={:?}", + "suggest_await_before_try: obligation={:?}, span={:?}, trait_pred={:?}, trait_pred_self_ty={:?}", obligation, span, - trait_ref, - trait_ref.self_ty() + trait_pred, + trait_pred.self_ty() ); let body_hir_id = obligation.cause.body_id; let item_id = self.tcx.hir().get_parent_node(body_hir_id); @@ -2444,7 +2450,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { if let Some(hir::GeneratorKind::Async(_)) = body.generator_kind { let future_trait = self.tcx.require_lang_item(LangItem::Future, None); - let self_ty = self.resolve_vars_if_possible(trait_ref.self_ty()); + let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty()); // Do not check on infer_types to avoid panic in evaluate_obligation. if self_ty.has_infer_types() { @@ -2464,7 +2470,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let projection_ty = ty::ProjectionTy { // `T` substs: self.tcx.mk_substs_trait( - trait_ref.self_ty().skip_binder(), + trait_pred.self_ty().skip_binder(), self.fresh_substs_for_item(span, item_def_id), ), // `Future::Output` @@ -2489,7 +2495,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ); let try_obligation = self.mk_trait_obligation_with_new_self_ty( obligation.param_env, - trait_ref, + trait_pred, normalized_ty, ); debug!("suggest_await_before_try: try_trait_obligation {:?}", try_obligation); diff --git a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs index 4840995275afa..6b20476b95594 100644 --- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs @@ -19,6 +19,7 @@ pub struct OnUnimplementedDirective { pub label: Option, pub note: Option, pub enclosing_scope: Option, + pub append_const_msg: Option>, } #[derive(Default)] @@ -27,6 +28,11 @@ pub struct OnUnimplementedNote { pub label: Option, pub note: Option, pub enclosing_scope: Option, + /// Append a message for `~const Trait` errors. `None` means not requested and + /// should fallback to a generic message, `Some(None)` suggests using the default + /// appended message, `Some(Some(s))` suggests use the `s` message instead of the + /// default one.. + pub append_const_msg: Option>, } fn parse_error( @@ -89,6 +95,7 @@ impl<'tcx> OnUnimplementedDirective { let mut note = None; let mut enclosing_scope = None; let mut subcommands = vec![]; + let mut append_const_msg = None; let parse_value = |value_str| { OnUnimplementedFormatString::try_parse(tcx, trait_def_id, value_str, span).map(Some) @@ -131,6 +138,14 @@ impl<'tcx> OnUnimplementedDirective { } continue; } + } else if item.has_name(sym::append_const_msg) && append_const_msg.is_none() { + if let Some(msg) = item.value_str() { + append_const_msg = Some(Some(msg)); + continue; + } else if item.is_word() { + append_const_msg = Some(None); + continue; + } } // nothing found @@ -153,6 +168,7 @@ impl<'tcx> OnUnimplementedDirective { label, note, enclosing_scope, + append_const_msg, }) } } @@ -183,6 +199,7 @@ impl<'tcx> OnUnimplementedDirective { )?), note: None, enclosing_scope: None, + append_const_msg: None, })) } else { return Err(ErrorReported); @@ -201,6 +218,7 @@ impl<'tcx> OnUnimplementedDirective { let mut label = None; let mut note = None; let mut enclosing_scope = None; + let mut append_const_msg = None; info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options); for command in self.subcommands.iter().chain(Some(self)).rev() { @@ -235,6 +253,8 @@ impl<'tcx> OnUnimplementedDirective { if let Some(ref enclosing_scope_) = command.enclosing_scope { enclosing_scope = Some(enclosing_scope_.clone()); } + + append_const_msg = command.append_const_msg.clone(); } let options: FxHashMap = @@ -244,6 +264,7 @@ impl<'tcx> OnUnimplementedDirective { message: message.map(|m| m.format(tcx, trait_ref, &options)), note: note.map(|n| n.format(tcx, trait_ref, &options)), enclosing_scope: enclosing_scope.map(|e_s| e_s.format(tcx, trait_ref, &options)), + append_const_msg, } } } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 3b6a4afafcfd1..2e20ea34e10ef 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -659,7 +659,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => bug!("closure candidate for non-closure {:?}", obligation), }; - let obligation_predicate = obligation.predicate.to_poly_trait_ref(); + let obligation_predicate = obligation.predicate; let Normalized { value: obligation_predicate, mut obligations } = ensure_sufficient_stack(|| { normalize_with_depth( @@ -689,7 +689,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligations.extend(self.confirm_poly_trait_refs( obligation.cause.clone(), obligation.param_env, - obligation_predicate, + obligation_predicate.to_poly_trait_ref(), trait_ref, )?); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index ab4fb9607ca00..ae53690548375 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2413,7 +2413,7 @@ impl<'tcx> TraitObligationExt<'tcx> for TraitObligation<'tcx> { // chain. Ideally, we should have a way to configure this either // by using -Z verbose or just a CLI argument. let derived_cause = DerivedObligationCause { - parent_trait_ref: obligation.predicate.to_poly_trait_ref(), + parent_trait_pred: obligation.predicate, parent_code: obligation.cause.clone_code(), }; let derived_code = variant(derived_cause); diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 195a4a4a653e1..2c5e7e40cc862 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -506,12 +506,21 @@ crate fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option WfPredicates<'a, 'tcx> { let extend = |obligation: traits::PredicateObligation<'tcx>| { let mut cause = cause.clone(); - if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_pred() { + if let Some(parent_trait_pred) = obligation.predicate.to_opt_poly_trait_pred() { let derived_cause = traits::DerivedObligationCause { - // FIXME(fee1-dead): when improving error messages, change this to PolyTraitPredicate - parent_trait_ref: parent_trait_ref.map_bound(|t| t.trait_ref), + parent_trait_pred, parent_code: obligation.cause.clone_code(), }; *cause.make_mut_code() = diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs index c39199f84b527..4b56cc5321b37 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs @@ -1021,7 +1021,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ObligationCauseCode::BuiltinDerivedObligation(code) | ObligationCauseCode::ImplDerivedObligation(code) | ObligationCauseCode::DerivedObligation(code) => { - code.parent_trait_ref.self_ty().skip_binder().into() + code.parent_trait_pred.self_ty().skip_binder().into() } _ if let ty::PredicateKind::Trait(predicate) = error.obligation.predicate.kind().skip_binder() => { diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 96ab800afaffe..7492b3a5f2797 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -823,9 +823,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => None, }) { - let parent_trait_ref = data.parent_trait_ref; + let parent_trait_ref = data.parent_trait_pred; let parent_def_id = parent_trait_ref.def_id(); - let path = parent_trait_ref.print_only_trait_path(); + let path = parent_trait_ref.print_modifiers_and_trait_path(); let tr_self_ty = parent_trait_ref.skip_binder().self_ty(); let mut candidates = vec![]; self.tcx.for_each_relevant_impl( diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index f89cf812e970a..1af352d542ac6 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -199,9 +199,20 @@ use self::Ordering::*; #[stable(feature = "rust1", since = "1.0.0")] #[doc(alias = "==")] #[doc(alias = "!=")] -#[rustc_on_unimplemented( - message = "can't compare `{Self}` with `{Rhs}`", - label = "no implementation for `{Self} == {Rhs}`" +#[cfg_attr( + bootstrap, + rustc_on_unimplemented( + message = "can't compare `{Self}` with `{Rhs}`", + label = "no implementation for `{Self} == {Rhs}`" + ) +)] +#[cfg_attr( + not(bootstrap), + rustc_on_unimplemented( + message = "can't compare `{Self}` with `{Rhs}`", + label = "no implementation for `{Self} == {Rhs}`", + append_const_msg, + ) )] #[rustc_diagnostic_item = "PartialEq"] pub trait PartialEq { @@ -1031,9 +1042,20 @@ impl PartialOrd for Ordering { #[doc(alias = "<")] #[doc(alias = "<=")] #[doc(alias = ">=")] -#[rustc_on_unimplemented( - message = "can't compare `{Self}` with `{Rhs}`", - label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`" +#[cfg_attr( + bootstrap, + rustc_on_unimplemented( + message = "can't compare `{Self}` with `{Rhs}`", + label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`", + ) +)] +#[cfg_attr( + not(bootstrap), + rustc_on_unimplemented( + message = "can't compare `{Self}` with `{Rhs}`", + label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`", + append_const_msg, + ) )] #[rustc_diagnostic_item = "PartialOrd"] pub trait PartialOrd: PartialEq { diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs index e954742938910..e367be8c167c7 100644 --- a/library/core/src/ops/arith.rs +++ b/library/core/src/ops/arith.rs @@ -65,11 +65,36 @@ /// ``` #[lang = "add"] #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_on_unimplemented( - on(all(_Self = "{integer}", Rhs = "{float}"), message = "cannot add a float to an integer",), - on(all(_Self = "{float}", Rhs = "{integer}"), message = "cannot add an integer to a float",), - message = "cannot add `{Rhs}` to `{Self}`", - label = "no implementation for `{Self} + {Rhs}`" +#[cfg_attr( + bootstrap, + rustc_on_unimplemented( + on( + all(_Self = "{integer}", Rhs = "{float}"), + message = "cannot add a float to an integer", + ), + on( + all(_Self = "{float}", Rhs = "{integer}"), + message = "cannot add an integer to a float", + ), + message = "cannot add `{Rhs}` to `{Self}`", + label = "no implementation for `{Self} + {Rhs}`" + ) +)] +#[cfg_attr( + not(bootstrap), + rustc_on_unimplemented( + on( + all(_Self = "{integer}", Rhs = "{float}"), + message = "cannot add a float to an integer", + ), + on( + all(_Self = "{float}", Rhs = "{integer}"), + message = "cannot add an integer to a float", + ), + message = "cannot add `{Rhs}` to `{Self}`", + label = "no implementation for `{Self} + {Rhs}`", + append_const_msg, + ) )] #[doc(alias = "+")] pub trait Add { diff --git a/src/test/ui/consts/const-block-const-bound.rs b/src/test/ui/consts/const-block-const-bound.rs index 3d7e171f18c05..f3c82c5f96816 100644 --- a/src/test/ui/consts/const-block-const-bound.rs +++ b/src/test/ui/consts/const-block-const-bound.rs @@ -16,8 +16,8 @@ impl !Drop for NonDrop {} fn main() { const { f(UnconstDrop); - //~^ ERROR the trait bound `UnconstDrop: Drop` is not satisfied + //~^ ERROR the trait bound `UnconstDrop: ~const Drop` is not satisfied f(NonDrop); - //~^ ERROR the trait bound `NonDrop: Drop` is not satisfied + //~^ ERROR the trait bound `NonDrop: ~const Drop` is not satisfied } } diff --git a/src/test/ui/consts/const-block-const-bound.stderr b/src/test/ui/consts/const-block-const-bound.stderr index 5f912c66bb97c..b5f5694ba8328 100644 --- a/src/test/ui/consts/const-block-const-bound.stderr +++ b/src/test/ui/consts/const-block-const-bound.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `UnconstDrop: Drop` is not satisfied +error[E0277]: the trait bound `UnconstDrop: ~const Drop` is not satisfied --> $DIR/const-block-const-bound.rs:18:11 | LL | f(UnconstDrop); - | - ^^^^^^^^^^^ the trait `Drop` is not implemented for `UnconstDrop` + | - ^^^^^^^^^^^ expected an implementor of trait `~const Drop` | | | required by a bound introduced by this call | @@ -11,16 +11,18 @@ note: required by a bound in `f` | LL | const fn f(x: T) {} | ^^^^^^^^^^^ required by this bound in `f` -help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement +help: consider borrowing here | -LL | fn main() where UnconstDrop: Drop { - | +++++++++++++++++++++++ +LL | f(&UnconstDrop); + | + +LL | f(&mut UnconstDrop); + | ++++ -error[E0277]: the trait bound `NonDrop: Drop` is not satisfied +error[E0277]: the trait bound `NonDrop: ~const Drop` is not satisfied --> $DIR/const-block-const-bound.rs:20:11 | LL | f(NonDrop); - | - ^^^^^^^ the trait `Drop` is not implemented for `NonDrop` + | - ^^^^^^^ expected an implementor of trait `~const Drop` | | | required by a bound introduced by this call | @@ -29,6 +31,12 @@ note: required by a bound in `f` | LL | const fn f(x: T) {} | ^^^^^^^^^^^ required by this bound in `f` +help: consider borrowing here + | +LL | f(&NonDrop); + | + +LL | f(&mut NonDrop); + | ++++ error: aborting due to 2 previous errors diff --git a/src/test/ui/intrinsics/const-eval-select-bad.rs b/src/test/ui/intrinsics/const-eval-select-bad.rs index a3171187e69e5..7d924e2b7f366 100644 --- a/src/test/ui/intrinsics/const-eval-select-bad.rs +++ b/src/test/ui/intrinsics/const-eval-select-bad.rs @@ -4,9 +4,9 @@ use std::intrinsics::const_eval_select; const fn not_fn_items() { const_eval_select((), || {}, || {}); - //~^ ERROR expected a `FnOnce<()>` closure + //~^ ERROR the trait bound const_eval_select((), 42, 0xDEADBEEF); - //~^ ERROR expected a `FnOnce<()>` closure + //~^ ERROR the trait bound //~| ERROR expected a `FnOnce<()>` closure } diff --git a/src/test/ui/intrinsics/const-eval-select-bad.stderr b/src/test/ui/intrinsics/const-eval-select-bad.stderr index 5e1ab584d80cf..083b00645388e 100644 --- a/src/test/ui/intrinsics/const-eval-select-bad.stderr +++ b/src/test/ui/intrinsics/const-eval-select-bad.stderr @@ -1,4 +1,4 @@ -error[E0277]: expected a `FnOnce<()>` closure, found `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]` +error[E0277]: the trait bound `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]: ~const FnOnce<()>` is not satisfied --> $DIR/const-eval-select-bad.rs:6:27 | LL | const_eval_select((), || {}, || {}); @@ -6,7 +6,7 @@ LL | const_eval_select((), || {}, || {}); | | | required by a bound introduced by this call | - = help: the trait `FnOnce<()>` is not implemented for `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]` + = help: the trait `~const FnOnce<()>` is not implemented for `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]` = note: wrap the `[closure@$DIR/const-eval-select-bad.rs:6:27: 6:32]` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `const_eval_select` --> $SRC_DIR/core/src/intrinsics.rs:LL:COL @@ -14,7 +14,7 @@ note: required by a bound in `const_eval_select` LL | F: ~const FnOnce, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select` -error[E0277]: expected a `FnOnce<()>` closure, found `{integer}` +error[E0277]: the trait bound `{integer}: ~const FnOnce<()>` is not satisfied --> $DIR/const-eval-select-bad.rs:8:27 | LL | const_eval_select((), 42, 0xDEADBEEF); @@ -22,7 +22,7 @@ LL | const_eval_select((), 42, 0xDEADBEEF); | | | required by a bound introduced by this call | - = help: the trait `FnOnce<()>` is not implemented for `{integer}` + = help: the trait `~const FnOnce<()>` is not implemented for `{integer}` = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `const_eval_select` --> $SRC_DIR/core/src/intrinsics.rs:LL:COL diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs index 7b012083c5a3d..99eacaa837f91 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs @@ -1,5 +1,5 @@ -// FIXME(fee1-dead): this should have a better error message #![feature(const_trait_impl)] + struct NonConstAdd(i32); impl std::ops::Add for NonConstAdd { @@ -16,7 +16,7 @@ trait Foo { impl const Foo for NonConstAdd { type Bar = NonConstAdd; - //~^ ERROR + //~^ ERROR: cannot add `NonConstAdd` to `NonConstAdd` in const contexts } trait Baz { diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr index 4a4b4de4758ba..429b9f3364be1 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr @@ -1,10 +1,10 @@ -error[E0277]: cannot add `NonConstAdd` to `NonConstAdd` +error[E0277]: cannot add `NonConstAdd` to `NonConstAdd` in const contexts --> $DIR/assoc-type.rs:18:16 | LL | type Bar = NonConstAdd; | ^^^^^^^^^^^ no implementation for `NonConstAdd + NonConstAdd` | - = help: the trait `Add` is not implemented for `NonConstAdd` + = help: the trait `~const Add` is not implemented for `NonConstAdd` note: required by a bound in `Foo::Bar` --> $DIR/assoc-type.rs:14:15 | @@ -12,8 +12,8 @@ LL | type Bar: ~const std::ops::Add; | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::Bar` help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement | -LL | impl const Foo for NonConstAdd where NonConstAdd: Add { - | ++++++++++++++++++++++ +LL | impl const Foo for NonConstAdd where NonConstAdd: ~const Add { + | +++++++++++++++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr index 0440f17a704de..13cffaba91a1d 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr @@ -1,4 +1,4 @@ -error[E0277]: can't compare `S` with `S` +error[E0277]: can't compare `S` with `S` in const contexts --> $DIR/call-generic-method-nonconst.rs:19:34 | LL | pub const EQ: bool = equals_self(&S); @@ -6,7 +6,7 @@ LL | pub const EQ: bool = equals_self(&S); | | | required by a bound introduced by this call | - = help: the trait `PartialEq` is not implemented for `S` + = help: the trait `~const PartialEq` is not implemented for `S` note: required by a bound in `equals_self` --> $DIR/call-generic-method-nonconst.rs:12:25 | diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr index 721636e074371..df776908a0365 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr @@ -1,26 +1,32 @@ -error[E0277]: the trait bound `NonTrivialDrop: Drop` is not satisfied +error[E0277]: the trait bound `NonTrivialDrop: ~const Drop` is not satisfied --> $DIR/const-drop-fail.rs:44:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call ... LL | NonTrivialDrop, - | ^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `NonTrivialDrop` + | ^^^^^^^^^^^^^^ expected an implementor of trait `~const Drop` | note: required by a bound in `check` --> $DIR/const-drop-fail.rs:35:19 | LL | const fn check(_: T) {} | ^^^^^^^^^^^ required by this bound in `check` +help: consider borrowing here + | +LL | &NonTrivialDrop, + | + +LL | &mut NonTrivialDrop, + | ++++ -error[E0277]: the trait bound `NonTrivialDrop: Drop` is not satisfied in `ConstImplWithDropGlue` +error[E0277]: the trait bound `NonTrivialDrop: ~const Drop` is not satisfied in `ConstImplWithDropGlue` --> $DIR/const-drop-fail.rs:46:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call ... LL | ConstImplWithDropGlue(NonTrivialDrop), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `Drop` is not implemented for `NonTrivialDrop` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Drop` is not implemented for `NonTrivialDrop` | note: required because it appears within the type `ConstImplWithDropGlue` --> $DIR/const-drop-fail.rs:17:8 @@ -33,16 +39,16 @@ note: required by a bound in `check` LL | const fn check(_: T) {} | ^^^^^^^^^^^ required by this bound in `check` -error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied +error[E0277]: the trait bound `ConstDropImplWithBounds: ~const Drop` is not satisfied --> $DIR/const-drop-fail.rs:48:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call ... LL | ConstDropImplWithBounds::(PhantomData), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `~const Drop` | -note: required because of the requirements on the impl of `Drop` for `ConstDropImplWithBounds` +note: required because of the requirements on the impl of `~const Drop` for `ConstDropImplWithBounds` --> $DIR/const-drop-fail.rs:29:25 | LL | impl const Drop for ConstDropImplWithBounds { @@ -52,6 +58,12 @@ note: required by a bound in `check` | LL | const fn check(_: T) {} | ^^^^^^^^^^^ required by this bound in `check` +help: consider borrowing here + | +LL | &ConstDropImplWithBounds::(PhantomData), + | + +LL | &mut ConstDropImplWithBounds::(PhantomData), + | ++++ error: aborting due to 3 previous errors diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr index 721636e074371..df776908a0365 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr @@ -1,26 +1,32 @@ -error[E0277]: the trait bound `NonTrivialDrop: Drop` is not satisfied +error[E0277]: the trait bound `NonTrivialDrop: ~const Drop` is not satisfied --> $DIR/const-drop-fail.rs:44:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call ... LL | NonTrivialDrop, - | ^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `NonTrivialDrop` + | ^^^^^^^^^^^^^^ expected an implementor of trait `~const Drop` | note: required by a bound in `check` --> $DIR/const-drop-fail.rs:35:19 | LL | const fn check(_: T) {} | ^^^^^^^^^^^ required by this bound in `check` +help: consider borrowing here + | +LL | &NonTrivialDrop, + | + +LL | &mut NonTrivialDrop, + | ++++ -error[E0277]: the trait bound `NonTrivialDrop: Drop` is not satisfied in `ConstImplWithDropGlue` +error[E0277]: the trait bound `NonTrivialDrop: ~const Drop` is not satisfied in `ConstImplWithDropGlue` --> $DIR/const-drop-fail.rs:46:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call ... LL | ConstImplWithDropGlue(NonTrivialDrop), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `Drop` is not implemented for `NonTrivialDrop` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Drop` is not implemented for `NonTrivialDrop` | note: required because it appears within the type `ConstImplWithDropGlue` --> $DIR/const-drop-fail.rs:17:8 @@ -33,16 +39,16 @@ note: required by a bound in `check` LL | const fn check(_: T) {} | ^^^^^^^^^^^ required by this bound in `check` -error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied +error[E0277]: the trait bound `ConstDropImplWithBounds: ~const Drop` is not satisfied --> $DIR/const-drop-fail.rs:48:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call ... LL | ConstDropImplWithBounds::(PhantomData), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `~const Drop` | -note: required because of the requirements on the impl of `Drop` for `ConstDropImplWithBounds` +note: required because of the requirements on the impl of `~const Drop` for `ConstDropImplWithBounds` --> $DIR/const-drop-fail.rs:29:25 | LL | impl const Drop for ConstDropImplWithBounds { @@ -52,6 +58,12 @@ note: required by a bound in `check` | LL | const fn check(_: T) {} | ^^^^^^^^^^^ required by this bound in `check` +help: consider borrowing here + | +LL | &ConstDropImplWithBounds::(PhantomData), + | + +LL | &mut ConstDropImplWithBounds::(PhantomData), + | ++++ error: aborting due to 3 previous errors diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs index 7db04fe1ac3f1..76ea17159ac79 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs @@ -10,7 +10,7 @@ pub trait Foo { #[default_method_body_is_const] fn foo() { foo::<()>(); - //~^ ERROR the trait bound `(): Tr` is not satisfied + //~^ ERROR the trait bound `(): ~const Tr` is not satisfied } } diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr index 6e7e4b3a472d6..05a74757b94f1 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `(): Tr` is not satisfied +error[E0277]: the trait bound `(): ~const Tr` is not satisfied --> $DIR/default-method-body-is-const-body-checking.rs:12:15 | LL | foo::<()>(); - | ^^ the trait `Tr` is not implemented for `()` + | ^^ the trait `~const Tr` is not implemented for `()` | note: required by a bound in `foo` --> $DIR/default-method-body-is-const-body-checking.rs:7:28 @@ -11,8 +11,8 @@ LL | const fn foo() where T: ~const Tr {} | ^^^^^^^^^ required by this bound in `foo` help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement | -LL | pub trait Foo where (): Tr { - | ++++++++++++ +LL | pub trait Foo where (): ~const Tr { + | +++++++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr index 08d91d7daf85b..903cd924ca55b 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `T: Bar` is not satisfied +error[E0277]: the trait bound `T: ~const Bar` is not satisfied --> $DIR/trait-where-clause.rs:14:5 | LL | T::b(); - | ^^^^ the trait `Bar` is not implemented for `T` + | ^^^^ the trait `~const Bar` is not implemented for `T` | note: required by a bound in `Foo::b` --> $DIR/trait-where-clause.rs:8:24 @@ -11,14 +11,14 @@ LL | fn b() where Self: ~const Bar; | ^^^^^^^^^^ required by this bound in `Foo::b` help: consider further restricting this bound | -LL | const fn test1() { - | +++++ +LL | const fn test1() { + | ++++++++++++ -error[E0277]: the trait bound `T: Bar` is not satisfied +error[E0277]: the trait bound `T: ~const Bar` is not satisfied --> $DIR/trait-where-clause.rs:16:5 | LL | T::c::(); - | ^^^^^^^^^ the trait `Bar` is not implemented for `T` + | ^^^^^^^^^ the trait `~const Bar` is not implemented for `T` | note: required by a bound in `Foo::c` --> $DIR/trait-where-clause.rs:9:13 @@ -27,8 +27,8 @@ LL | fn c(); | ^^^^^^^^^^ required by this bound in `Foo::c` help: consider further restricting this bound | -LL | const fn test1() { - | +++++ +LL | const fn test1() { + | ++++++++++++ error[E0277]: the trait bound `T: Bar` is not satisfied --> $DIR/trait-where-clause.rs:28:5