1
Fork 0

Improve selection errors for ~const trait bounds

This commit is contained in:
Deadbeef 2021-12-24 22:50:44 +08:00
parent 17dfae79bb
commit fdf7d01088
No known key found for this signature in database
GPG key ID: 6D017A96D8E6C2F9
23 changed files with 323 additions and 203 deletions

View file

@ -402,7 +402,7 @@ impl ObligationCauseCode<'_> {
// `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger. // `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] #[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)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum StatementAsExpression { pub enum StatementAsExpression {
@ -440,11 +440,11 @@ pub struct IfExpressionCause {
#[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)] #[derive(Clone, Debug, PartialEq, Eq, Hash, Lift)]
pub struct DerivedObligationCause<'tcx> { 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 /// 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. /// directly.
pub parent_trait_ref: ty::PolyTraitRef<'tcx>, pub parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
/// The parent trait had this cause. /// The parent trait had this cause.
pub parent_code: Lrc<ObligationCauseCode<'tcx>>, pub parent_code: Lrc<ObligationCauseCode<'tcx>>,

View file

@ -766,6 +766,17 @@ impl<'tcx> TraitPredicate<'tcx> {
*param_env = param_env.with_constness(self.constness.and(param_env.constness())) *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 { pub fn def_id(self) -> DefId {
self.trait_ref.def_id self.trait_ref.def_id
} }
@ -784,6 +795,14 @@ impl<'tcx> PolyTraitPredicate<'tcx> {
pub fn self_ty(self) -> ty::Binder<'tcx, Ty<'tcx>> { pub fn self_ty(self) -> ty::Binder<'tcx, Ty<'tcx>> {
self.map_bound(|trait_ref| trait_ref.self_ty()) 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)] #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]

View file

@ -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! { forward_display_to_print! {
Ty<'tcx>, Ty<'tcx>,
&'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>, &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>,
@ -2427,6 +2450,7 @@ forward_display_to_print! {
ty::Binder<'tcx, TraitRefPrintOnlyTraitName<'tcx>>, ty::Binder<'tcx, TraitRefPrintOnlyTraitName<'tcx>>,
ty::Binder<'tcx, ty::FnSig<'tcx>>, ty::Binder<'tcx, ty::FnSig<'tcx>>,
ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
ty::Binder<'tcx, TraitPredPrintModifiersAndPath<'tcx>>,
ty::Binder<'tcx, ty::SubtypePredicate<'tcx>>, ty::Binder<'tcx, ty::SubtypePredicate<'tcx>>,
ty::Binder<'tcx, ty::ProjectionPredicate<'tcx>>, ty::Binder<'tcx, ty::ProjectionPredicate<'tcx>>,
ty::Binder<'tcx, ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>, ty::Binder<'tcx, ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>,
@ -2491,6 +2515,18 @@ define_print_and_forward_display! {
p!(print_def_path(self.0.def_id, &[])); 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 { ty::ParamTy {
p!(write("{}", self.name)) p!(write("{}", self.name))
} }
@ -2508,8 +2544,11 @@ define_print_and_forward_display! {
} }
ty::TraitPredicate<'tcx> { ty::TraitPredicate<'tcx> {
p!(print(self.trait_ref.self_ty()), ": ", p!(print(self.trait_ref.self_ty()), ": ");
print(self.trait_ref.print_only_trait_path())) if let ty::BoundConstness::ConstIfConst = self.constness {
p!("~const ");
}
p!(print(self.trait_ref.print_only_trait_path()))
} }
ty::ProjectionPredicate<'tcx> { ty::ProjectionPredicate<'tcx> {

View file

@ -205,6 +205,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
self.note_obligation_cause_code( self.note_obligation_cause_code(
&mut err, &mut err,
&obligation.predicate, &obligation.predicate,
obligation.param_env,
obligation.cause.code(), obligation.cause.code(),
&mut vec![], &mut vec![],
&mut Default::default(), &mut Default::default(),
@ -288,7 +289,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
match bound_predicate.skip_binder() { match bound_predicate.skip_binder() {
ty::PredicateKind::Trait(trait_predicate) => { ty::PredicateKind::Trait(trait_predicate) => {
let trait_predicate = bound_predicate.rebind(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() { if self.tcx.sess.has_errors() && trait_predicate.references_error() {
return; return;
@ -332,11 +337,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
span, span,
E0277, E0277,
"{}", "{}",
message.unwrap_or_else(|| format!( (!predicate_is_const).then(|| message).flatten().unwrap_or_else(
"the trait bound `{}` is not satisfied{}", || format!(
trait_ref.without_const().to_predicate(tcx), "the trait bound `{}` is not satisfied{}",
post_message, trait_predicate, post_message,
)) )
)
); );
if is_try_conversion { if is_try_conversion {
@ -384,7 +390,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
format!( format!(
"{}the trait `{}` is not implemented for `{}`", "{}the trait `{}` is not implemented for `{}`",
pre_message, pre_message,
trait_ref.print_only_trait_path(), trait_predicate.print_modifiers_and_trait_path(),
trait_ref.skip_binder().self_ty(), trait_ref.skip_binder().self_ty(),
) )
}; };
@ -392,7 +398,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
if self.suggest_add_reference_to_arg( if self.suggest_add_reference_to_arg(
&obligation, &obligation,
&mut err, &mut err,
&trait_ref, trait_predicate,
have_alt_message, have_alt_message,
) { ) {
self.note_obligation_cause(&mut err, &obligation); self.note_obligation_cause(&mut err, &obligation);
@ -435,18 +441,28 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
err.span_label(enclosing_scope_span, s.as_str()); err.span_label(enclosing_scope_span, s.as_str());
} }
self.suggest_dereferences(&obligation, &mut err, trait_ref); self.suggest_dereferences(&obligation, &mut err, trait_predicate);
self.suggest_fn_call(&obligation, &mut err, trait_ref); self.suggest_fn_call(&obligation, &mut err, trait_predicate);
self.suggest_remove_reference(&obligation, &mut err, trait_ref); self.suggest_remove_reference(&obligation, &mut err, trait_predicate);
self.suggest_semicolon_removal(&obligation, &mut err, span, trait_ref); self.suggest_semicolon_removal(
&obligation,
&mut err,
span,
trait_predicate,
);
self.note_version_mismatch(&mut err, &trait_ref); self.note_version_mismatch(&mut err, &trait_ref);
self.suggest_remove_await(&obligation, &mut err); self.suggest_remove_await(&obligation, &mut err);
if Some(trait_ref.def_id()) == tcx.lang_items().try_trait() { 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(); err.emit();
return; return;
} }
@ -494,7 +510,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// which is somewhat confusing. // which is somewhat confusing.
self.suggest_restricting_param_bound( self.suggest_restricting_param_bound(
&mut err, &mut err,
trait_ref, trait_predicate,
obligation.cause.body_id, obligation.cause.body_id,
); );
} else if !have_alt_message { } else if !have_alt_message {
@ -506,7 +522,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// 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_ref); self.suggest_change_mut(&obligation, &mut err, 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
@ -1121,7 +1137,7 @@ trait InferCtxtPrivExt<'hir, 'tcx> {
fn mk_trait_obligation_with_new_self_ty( fn mk_trait_obligation_with_new_self_ty(
&self, &self,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>, trait_ref: ty::PolyTraitPredicate<'tcx>,
new_self_ty: Ty<'tcx>, new_self_ty: Ty<'tcx>,
) -> PredicateObligation<'tcx>; ) -> PredicateObligation<'tcx>;
@ -1540,7 +1556,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
) -> Option<(String, Option<Span>)> { ) -> Option<(String, Option<Span>)> {
match code { match code {
ObligationCauseCode::BuiltinDerivedObligation(data) => { 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) { match self.get_parent_trait_ref(&data.parent_code) {
Some(t) => Some(t), Some(t) => Some(t),
None => { None => {
@ -1593,21 +1609,20 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
fn mk_trait_obligation_with_new_self_ty( fn mk_trait_obligation_with_new_self_ty(
&self, &self,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>, trait_ref: ty::PolyTraitPredicate<'tcx>,
new_self_ty: Ty<'tcx>, new_self_ty: Ty<'tcx>,
) -> PredicateObligation<'tcx> { ) -> PredicateObligation<'tcx> {
assert!(!new_self_ty.has_escaping_bound_vars()); assert!(!new_self_ty.has_escaping_bound_vars());
let trait_ref = trait_ref.map_bound_ref(|tr| ty::TraitRef { let trait_pred = trait_ref.map_bound_ref(|tr| ty::TraitPredicate {
substs: self.tcx.mk_substs_trait(new_self_ty, &tr.substs[1..]), trait_ref: ty::TraitRef {
substs: self.tcx.mk_substs_trait(new_self_ty, &tr.trait_ref.substs[1..]),
..tr.trait_ref
},
..*tr ..*tr
}); });
Obligation::new( Obligation::new(ObligationCause::dummy(), param_env, trait_pred.to_predicate(self.tcx))
ObligationCause::dummy(),
param_env,
trait_ref.without_const().to_predicate(self.tcx),
)
} }
#[instrument(skip(self), level = "debug")] #[instrument(skip(self), level = "debug")]
@ -2008,6 +2023,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
self.note_obligation_cause_code( self.note_obligation_cause_code(
err, err,
&obligation.predicate, &obligation.predicate,
obligation.param_env,
obligation.cause.code(), obligation.cause.code(),
&mut vec![], &mut vec![],
&mut Default::default(), &mut Default::default(),
@ -2155,7 +2171,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
cause_code: &ObligationCauseCode<'tcx>, cause_code: &ObligationCauseCode<'tcx>,
) -> bool { ) -> bool {
if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code { 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(); let self_ty = parent_trait_ref.skip_binder().self_ty();
if obligated_types.iter().any(|ot| ot == &self_ty) { if obligated_types.iter().any(|ot| ot == &self_ty) {
return true; return true;

View file

@ -48,7 +48,7 @@ pub trait InferCtxtExt<'tcx> {
fn suggest_restricting_param_bound( fn suggest_restricting_param_bound(
&self, &self,
err: &mut DiagnosticBuilder<'_>, err: &mut DiagnosticBuilder<'_>,
trait_ref: ty::PolyTraitRef<'tcx>, trait_pred: ty::PolyTraitPredicate<'tcx>,
body_id: hir::HirId, body_id: hir::HirId,
); );
@ -56,7 +56,7 @@ pub trait InferCtxtExt<'tcx> {
&self, &self,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'tcx>, err: &mut DiagnosticBuilder<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>, trait_pred: ty::PolyTraitPredicate<'tcx>,
); );
fn get_closure_name( fn get_closure_name(
@ -70,14 +70,14 @@ pub trait InferCtxtExt<'tcx> {
&self, &self,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>, err: &mut DiagnosticBuilder<'_>,
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, trait_pred: ty::PolyTraitPredicate<'tcx>,
); );
fn suggest_add_reference_to_arg( fn suggest_add_reference_to_arg(
&self, &self,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>, err: &mut DiagnosticBuilder<'_>,
trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>, trait_pred: ty::PolyTraitPredicate<'tcx>,
has_custom_message: bool, has_custom_message: bool,
) -> bool; ) -> bool;
@ -85,7 +85,7 @@ pub trait InferCtxtExt<'tcx> {
&self, &self,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>, err: &mut DiagnosticBuilder<'_>,
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, trait_pred: ty::PolyTraitPredicate<'tcx>,
); );
fn suggest_remove_await( fn suggest_remove_await(
@ -98,7 +98,7 @@ pub trait InferCtxtExt<'tcx> {
&self, &self,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>, err: &mut DiagnosticBuilder<'_>,
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, trait_pred: ty::PolyTraitPredicate<'tcx>,
); );
fn suggest_semicolon_removal( fn suggest_semicolon_removal(
@ -106,7 +106,7 @@ pub trait InferCtxtExt<'tcx> {
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>, err: &mut DiagnosticBuilder<'_>,
span: Span, span: Span,
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, trait_pred: ty::PolyTraitPredicate<'tcx>,
); );
fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span>; fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span>;
@ -116,7 +116,7 @@ pub trait InferCtxtExt<'tcx> {
err: &mut DiagnosticBuilder<'_>, err: &mut DiagnosticBuilder<'_>,
span: Span, span: Span,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> bool; ) -> bool;
fn point_at_returns_when_relevant( fn point_at_returns_when_relevant(
@ -154,7 +154,7 @@ pub trait InferCtxtExt<'tcx> {
interior_extra_info: Option<(Option<Span>, Span, Option<hir::HirId>, Option<Span>)>, interior_extra_info: Option<(Option<Span>, Span, Option<hir::HirId>, Option<Span>)>,
inner_generator_body: Option<&hir::Body<'tcx>>, inner_generator_body: Option<&hir::Body<'tcx>>,
outer_generator: Option<DefId>, outer_generator: Option<DefId>,
trait_ref: ty::TraitRef<'tcx>, trait_pred: ty::TraitPredicate<'tcx>,
target_ty: Ty<'tcx>, target_ty: Ty<'tcx>,
typeck_results: Option<&ty::TypeckResults<'tcx>>, typeck_results: Option<&ty::TypeckResults<'tcx>>,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
@ -165,6 +165,7 @@ pub trait InferCtxtExt<'tcx> {
&self, &self,
err: &mut DiagnosticBuilder<'_>, err: &mut DiagnosticBuilder<'_>,
predicate: &T, predicate: &T,
param_env: ty::ParamEnv<'tcx>,
cause_code: &ObligationCauseCode<'tcx>, cause_code: &ObligationCauseCode<'tcx>,
obligated_types: &mut Vec<&ty::TyS<'tcx>>, obligated_types: &mut Vec<&ty::TyS<'tcx>>,
seen_requirements: &mut FxHashSet<DefId>, seen_requirements: &mut FxHashSet<DefId>,
@ -178,7 +179,7 @@ pub trait InferCtxtExt<'tcx> {
&self, &self,
err: &mut DiagnosticBuilder<'_>, err: &mut DiagnosticBuilder<'_>,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, trait_pred: ty::PolyTraitPredicate<'tcx>,
span: Span, span: Span,
); );
} }
@ -204,7 +205,7 @@ fn suggest_restriction<'tcx>(
err: &mut DiagnosticBuilder<'_>, err: &mut DiagnosticBuilder<'_>,
fn_sig: Option<&hir::FnSig<'_>>, fn_sig: Option<&hir::FnSig<'_>>,
projection: Option<&ty::ProjectionTy<'_>>, projection: Option<&ty::ProjectionTy<'_>>,
trait_ref: ty::PolyTraitRef<'tcx>, trait_pred: ty::PolyTraitPredicate<'tcx>,
super_traits: Option<(&Ident, &hir::GenericBounds<'_>)>, super_traits: Option<(&Ident, &hir::GenericBounds<'_>)>,
) { ) {
// When we are dealing with a trait, `super_traits` will be `Some`: // 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. // The type param `T: Trait` we will suggest to introduce.
let type_param = format!("{}: {}", type_param_name, bound_str); 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 `<impl Trait as Foo>::Bar: Qux` into `<T as Foo>::Bar: Qux`. // Turn `<impl Trait as Foo>::Bar: Qux` into `<T as Foo>::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 pred = pred.replace(&impl_trait_str, &type_param_name);
let mut sugg = vec![ let mut sugg = vec![
// Find the last of the generic parameters contained within the span of // 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, .. })), .find(|p| !matches!(p.kind, hir::GenericParamKind::Type { synthetic: true, .. })),
super_traits, super_traits,
) { ) {
(_, None) => predicate_constraint( (_, None) => predicate_constraint(generics, trait_pred.to_predicate(tcx).to_string()),
generics, (None, Some((ident, []))) => (
trait_ref.without_const().to_predicate(tcx).to_string(), 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( err.span_suggestion_verbose(
@ -329,10 +330,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
fn suggest_restricting_param_bound( fn suggest_restricting_param_bound(
&self, &self,
mut err: &mut DiagnosticBuilder<'_>, mut err: &mut DiagnosticBuilder<'_>,
trait_ref: ty::PolyTraitRef<'tcx>, trait_pred: ty::PolyTraitPredicate<'tcx>,
body_id: hir::HirId, 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() { let (param_ty, projection) = match self_ty.kind() {
ty::Param(_) => (true, None), ty::Param(_) => (true, None),
ty::Projection(projection) => (false, Some(projection)), ty::Projection(projection) => (false, Some(projection)),
@ -358,7 +359,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
err, err,
None, None,
projection, projection,
trait_ref, trait_pred,
Some((ident, bounds)), Some((ident, bounds)),
); );
return; return;
@ -372,7 +373,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
assert!(param_ty); assert!(param_ty);
// Restricting `Self` for a single method. // Restricting `Self` for a single method.
suggest_restriction( suggest_restriction(
self.tcx, &generics, "`Self`", err, None, projection, trait_ref, None, self.tcx, &generics, "`Self`", err, None, projection, trait_pred, None,
); );
return; return;
} }
@ -398,7 +399,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
err, err,
Some(fn_sig), Some(fn_sig),
projection, projection,
trait_ref, trait_pred,
None, None,
); );
return; return;
@ -417,7 +418,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
err, err,
None, None,
projection, projection,
trait_ref, trait_pred,
None, None,
); );
return; return;
@ -442,15 +443,16 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
{ {
// Missing generic type parameter bound. // Missing generic type parameter bound.
let param_name = self_ty.to_string(); let param_name = self_ty.to_string();
let constraint = let constraint = with_no_trimmed_paths(|| {
with_no_trimmed_paths(|| trait_ref.print_only_trait_path().to_string()); trait_pred.print_modifiers_and_trait_path().to_string()
});
if suggest_constraining_type_param( if suggest_constraining_type_param(
self.tcx, self.tcx,
generics, generics,
&mut err, &mut err,
&param_name, &param_name,
&constraint, &constraint,
Some(trait_ref.def_id()), Some(trait_pred.def_id()),
) { ) {
return; return;
} }
@ -471,7 +473,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
}) if !param_ty => { }) if !param_ty => {
// Missing generic type parameter bound. // Missing generic type parameter bound.
let param_name = self_ty.to_string(); 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, &param_name, &constraint) { if suggest_arbitrary_trait_bound(generics, &mut err, &param_name, &constraint) {
return; return;
} }
@ -492,7 +494,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
&self, &self,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'tcx>, err: &mut DiagnosticBuilder<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>, trait_pred: ty::PolyTraitPredicate<'tcx>,
) { ) {
// It only make sense when suggesting dereferences for arguments // It only make sense when suggesting dereferences for arguments
let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } = 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 param_env = obligation.param_env;
let body_id = obligation.cause.body_id; let body_id = obligation.cause.body_id;
let span = obligation.cause.span; let span = obligation.cause.span;
let real_trait_ref = match &*code { let real_trait_pred = match &*code {
ObligationCauseCode::ImplDerivedObligation(cause) ObligationCauseCode::ImplDerivedObligation(cause)
| ObligationCauseCode::DerivedObligation(cause) | ObligationCauseCode::DerivedObligation(cause)
| ObligationCauseCode::BuiltinDerivedObligation(cause) => cause.parent_trait_ref, | ObligationCauseCode::BuiltinDerivedObligation(cause) => cause.parent_trait_pred,
_ => trait_ref, _ => 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, Some(ty) => ty,
None => return, None => return,
}; };
@ -522,7 +524,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// Re-add the `&` // Re-add the `&`
let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl }); let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl });
let obligation = 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)) Some(steps).filter(|_| self.predicate_may_hold(&obligation))
}) { }) {
if steps > 0 { if steps > 0 {
@ -589,9 +591,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
&self, &self,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>, 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, None => return,
Some(ty) => ty, Some(ty) => ty,
}; };
@ -611,7 +613,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
}; };
let new_obligation = 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) { match self.evaluate_obligation(&new_obligation) {
Ok( Ok(
@ -682,7 +684,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
&self, &self,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>, err: &mut DiagnosticBuilder<'_>,
poly_trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>, poly_trait_pred: ty::PolyTraitPredicate<'tcx>,
has_custom_message: bool, has_custom_message: bool,
) -> bool { ) -> bool {
let span = obligation.cause.span; let span = obligation.cause.span;
@ -715,24 +717,18 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
let param_env = obligation.param_env; let param_env = obligation.param_env;
// Try to apply the original trait binding obligation by borrowing. // 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]| blacklist: &[DefId]|
-> bool { -> bool {
if blacklist.contains(&old_ref.def_id()) { if blacklist.contains(&old_pred.def_id()) {
return false; 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 mk_result = |new_ty| {
let new_ref = old_ref.rebind(ty::TraitRef::new( let obligation =
old_ref.def_id(), self.mk_trait_obligation_with_new_self_ty(param_env, old_pred, new_ty);
self.tcx.mk_substs_trait(new_ty, &old_ref.skip_binder().substs[1..]), self.predicate_must_hold_modulo_regions(&obligation)
));
self.predicate_must_hold_modulo_regions(&Obligation::new(
ObligationCause::dummy(),
param_env,
new_ref.without_const().to_predicate(self.tcx),
))
}; };
let imm_result = mk_result(self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, orig_ty)); 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)); 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!( let msg = format!(
"the trait bound `{}: {}` is not satisfied", "the trait bound `{}: {}` is not satisfied",
orig_ty, orig_ty,
old_ref.print_only_trait_path(), old_pred.print_modifiers_and_trait_path(),
); );
if has_custom_message { if has_custom_message {
err.note(&msg); err.note(&msg);
@ -764,7 +760,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
span, span,
&format!( &format!(
"expected an implementor of trait `{}`", "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 { if let ObligationCauseCode::ImplDerivedObligation(obligation) = code {
try_borrowing(obligation.parent_trait_ref, &[]) try_borrowing(obligation.parent_trait_pred, &[])
} else if let ObligationCauseCode::BindingObligation(_, _) } else if let ObligationCauseCode::BindingObligation(_, _)
| ObligationCauseCode::ItemObligation(_) = code | ObligationCauseCode::ItemObligation(_) = code
{ {
try_borrowing(*poly_trait_ref, &never_suggest_borrow) try_borrowing(poly_trait_pred, &never_suggest_borrow)
} else { } else {
false false
} }
@ -822,7 +818,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
&self, &self,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>, err: &mut DiagnosticBuilder<'_>,
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, trait_pred: ty::PolyTraitPredicate<'tcx>,
) { ) {
let span = obligation.cause.span; let span = obligation.cause.span;
@ -834,7 +830,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
return; 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, Some(ty) => ty,
None => return, 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( let new_obligation = self.mk_trait_obligation_with_new_self_ty(
obligation.param_env, obligation.param_env,
trait_ref, trait_pred,
suggested_ty, suggested_ty,
); );
@ -941,7 +937,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
&self, &self,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>, err: &mut DiagnosticBuilder<'_>,
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, trait_pred: ty::PolyTraitPredicate<'tcx>,
) { ) {
let points_at_arg = matches!( let points_at_arg = matches!(
obligation.cause.code(), 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. // Do not suggest removal of borrow from type arguments.
return; return;
} }
let trait_ref = self.resolve_vars_if_possible(trait_ref); let trait_pred = self.resolve_vars_if_possible(trait_pred);
if trait_ref.has_infer_types_or_consts() { if trait_pred.has_infer_types_or_consts() {
// Do not ICE while trying to find if a reborrow would succeed on a trait with // Do not ICE while trying to find if a reborrow would succeed on a trait with
// unresolved bindings. // unresolved bindings.
return; 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() { if region.is_late_bound() || t_type.has_escaping_bound_vars() {
// Avoid debug assertion in `mk_obligation_for_def_id`. // 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( let new_obligation = self.mk_trait_obligation_with_new_self_ty(
obligation.param_env, obligation.param_env,
trait_ref, trait_pred,
suggested_ty, suggested_ty,
); );
let suggested_ty_would_satisfy_obligation = self let suggested_ty_would_satisfy_obligation = self
@ -1002,9 +999,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
} else { } else {
err.note(&format!( err.note(&format!(
"`{}` is implemented for `{:?}`, but not for `{:?}`", "`{}` is implemented for `{:?}`, but not for `{:?}`",
trait_ref.print_only_trait_path(), trait_pred.print_modifiers_and_trait_path(),
suggested_ty, 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>, obligation: &PredicateObligation<'tcx>,
err: &mut DiagnosticBuilder<'_>, err: &mut DiagnosticBuilder<'_>,
span: Span, span: Span,
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, trait_pred: ty::PolyTraitPredicate<'tcx>,
) { ) {
let is_empty_tuple = let is_empty_tuple =
|ty: ty::Binder<'tcx, Ty<'_>>| *ty.skip_binder().kind() == ty::Tuple(ty::List::empty()); |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 let hir::ExprKind::Block(blk, _) = &body.value.kind {
if sig.decl.output.span().overlaps(span) if sig.decl.output.span().overlaps(span)
&& blk.expr.is_none() && 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 // FIXME(estebank): When encountering a method with a trait
// bound not satisfied in the return type with a body that has // 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<'_>, err: &mut DiagnosticBuilder<'_>,
span: Span, span: Span,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> bool { ) -> bool {
match obligation.cause.code().peel_derives() { match obligation.cause.code().peel_derives() {
// Only suggest `impl Trait` if the return type is unsized because it is `dyn Trait`. // 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; return false;
}; };
let body = hir.body(*body_id); let body = hir.body(*body_id);
let trait_ref = self.resolve_vars_if_possible(trait_ref); let trait_pred = self.resolve_vars_if_possible(trait_pred);
let ty = trait_ref.skip_binder().self_ty(); let ty = trait_pred.skip_binder().self_ty();
let is_object_safe = match ty.kind() { let is_object_safe = match ty.kind() {
ty::Dynamic(predicates, _) => { ty::Dynamic(predicates, _) => {
// If the `dyn Trait` is not object safe, do not suggest `Box<dyn Trait>`. // If the `dyn Trait` is not object safe, do not suggest `Box<dyn Trait>`.
@ -1326,9 +1323,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
trait_ref.rebind(sig).to_string() trait_ref.rebind(sig).to_string()
} }
let argument_kind = match expected_ref.skip_binder().substs.type_at(0) { let argument_kind = match expected_ref.skip_binder().self_ty().kind() {
t if t.is_closure() => "closure", ty::Closure(..) => "closure",
t if t.is_generator() => "generator", ty::Generator(..) => "generator",
_ => "function", _ => "function",
}; };
let mut err = struct_span_err!( 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 // bound was introduced. At least one generator should be present for this diagnostic to be
// modified. // modified.
let (mut trait_ref, mut target_ty) = match obligation.predicate.kind().skip_binder() { 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), _ => (None, None),
}; };
let mut generator = None; let mut generator = None;
@ -1473,11 +1470,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
ObligationCauseCode::DerivedObligation(derived_obligation) ObligationCauseCode::DerivedObligation(derived_obligation)
| ObligationCauseCode::BuiltinDerivedObligation(derived_obligation) | ObligationCauseCode::BuiltinDerivedObligation(derived_obligation)
| ObligationCauseCode::ImplDerivedObligation(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!( debug!(
"maybe_note_obligation_cause_for_async_await: \ "maybe_note_obligation_cause_for_async_await: \
parent_trait_ref={:?} self_ty.kind={:?}", parent_trait_ref={:?} self_ty.kind={:?}",
derived_obligation.parent_trait_ref, derived_obligation.parent_trait_pred,
ty.kind() ty.kind()
); );
@ -1495,7 +1492,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
seen_upvar_tys_infer_tuple = true; seen_upvar_tys_infer_tuple = true;
} }
_ if generator.is_none() => { _ 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); target_ty = Some(ty);
} }
_ => {} _ => {}
@ -1651,7 +1648,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
interior_extra_info: Option<(Option<Span>, Span, Option<hir::HirId>, Option<Span>)>, interior_extra_info: Option<(Option<Span>, Span, Option<hir::HirId>, Option<Span>)>,
inner_generator_body: Option<&hir::Body<'tcx>>, inner_generator_body: Option<&hir::Body<'tcx>>,
outer_generator: Option<DefId>, outer_generator: Option<DefId>,
trait_ref: ty::TraitRef<'tcx>, trait_pred: ty::TraitPredicate<'tcx>,
target_ty: Ty<'tcx>, target_ty: Ty<'tcx>,
typeck_results: Option<&ty::TypeckResults<'tcx>>, typeck_results: Option<&ty::TypeckResults<'tcx>>,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
@ -1671,7 +1668,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// not implemented. // not implemented.
let hir = self.tcx.hir(); let hir = self.tcx.hir();
let trait_explanation = if let Some(name @ (sym::Send | sym::Sync)) = 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) = let (trait_name, trait_verb) =
if name == sym::Send { ("`Send`", "sent") } else { ("`Sync`", "shared") }; 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) format!("is not {}", trait_name)
} else { } 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, 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( self.note_obligation_cause_code(
err, err,
&obligation.predicate, &obligation.predicate,
obligation.param_env,
next_code.unwrap(), next_code.unwrap(),
&mut Vec::new(), &mut Vec::new(),
&mut Default::default(), &mut Default::default(),
@ -1904,6 +1902,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
&self, &self,
err: &mut DiagnosticBuilder<'_>, err: &mut DiagnosticBuilder<'_>,
predicate: &T, predicate: &T,
param_env: ty::ParamEnv<'tcx>,
cause_code: &ObligationCauseCode<'tcx>, cause_code: &ObligationCauseCode<'tcx>,
obligated_types: &mut Vec<&ty::TyS<'tcx>>, obligated_types: &mut Vec<&ty::TyS<'tcx>>,
seen_requirements: &mut FxHashSet<DefId>, seen_requirements: &mut FxHashSet<DefId>,
@ -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`"); err.note("shared static variables must have a type that implements `Sync`");
} }
ObligationCauseCode::BuiltinDerivedObligation(ref data) => { 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(); let ty = parent_trait_ref.skip_binder().self_ty();
if parent_trait_ref.references_error() { if parent_trait_ref.references_error() {
err.cancel(); err.cancel();
@ -2149,7 +2148,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = if let ObligationCauseCode::BuiltinDerivedObligation(ref data) =
*data.parent_code *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(); let ty = parent_trait_ref.skip_binder().self_ty();
matches!(ty.kind(), ty::Generator(..)) matches!(ty.kind(), ty::Generator(..))
|| matches!(ty.kind(), ty::Closure(..)) || matches!(ty.kind(), ty::Closure(..))
@ -2172,13 +2172,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
obligated_types.push(ty); 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) { if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
// #74711: avoid a stack overflow // #74711: avoid a stack overflow
ensure_sufficient_stack(|| { ensure_sufficient_stack(|| {
self.note_obligation_cause_code( self.note_obligation_cause_code(
err, err,
&parent_predicate, &parent_predicate,
param_env,
&data.parent_code, &data.parent_code,
obligated_types, obligated_types,
seen_requirements, seen_requirements,
@ -2189,6 +2190,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
self.note_obligation_cause_code( self.note_obligation_cause_code(
err, err,
&parent_predicate, &parent_predicate,
param_env,
&cause_code.peel_derives(), &cause_code.peel_derives(),
obligated_types, obligated_types,
seen_requirements, seen_requirements,
@ -2197,17 +2199,18 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
} }
} }
ObligationCauseCode::ImplDerivedObligation(ref data) => { ObligationCauseCode::ImplDerivedObligation(ref data) => {
let mut parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_ref); let mut parent_trait_pred = self.resolve_vars_if_possible(data.parent_trait_pred);
let parent_def_id = parent_trait_ref.def_id(); parent_trait_pred.remap_constness_diag(param_env);
let parent_def_id = parent_trait_pred.def_id();
let msg = format!( let msg = format!(
"required because of the requirements on the impl of `{}` for `{}`", "required because of the requirements on the impl of `{}` for `{}`",
parent_trait_ref.print_only_trait_path(), parent_trait_pred.print_modifiers_and_trait_path(),
parent_trait_ref.skip_binder().self_ty() parent_trait_pred.skip_binder().self_ty()
); );
let mut candidates = vec![]; let mut candidates = vec![];
self.tcx.for_each_relevant_impl( self.tcx.for_each_relevant_impl(
parent_def_id, 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) { |impl_def_id| match self.tcx.hir().get_if_local(impl_def_id) {
Some(Node::Item(hir::Item { Some(Node::Item(hir::Item {
kind: hir::ItemKind::Impl(hir::Impl { .. }), kind: hir::ItemKind::Impl(hir::Impl { .. }),
@ -2236,21 +2239,21 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
_ => err.note(&msg), _ => 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 data = data;
let mut count = 0; let mut count = 0;
seen_requirements.insert(parent_def_id); seen_requirements.insert(parent_def_id);
while let ObligationCauseCode::ImplDerivedObligation(child) = &*data.parent_code { while let ObligationCauseCode::ImplDerivedObligation(child) = &*data.parent_code {
// Skip redundant recursive obligation notes. See `ui/issue-20413.rs`. // 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_trait_pred = self.resolve_vars_if_possible(child.parent_trait_pred);
let child_def_id = child_trait_ref.def_id(); let child_def_id = child_trait_pred.def_id();
if seen_requirements.insert(child_def_id) { if seen_requirements.insert(child_def_id) {
break; break;
} }
count += 1; count += 1;
data = child; data = child;
parent_predicate = child_trait_ref.without_const().to_predicate(tcx); parent_predicate = child_trait_pred.to_predicate(tcx);
parent_trait_ref = child_trait_ref; parent_trait_pred = child_trait_pred;
} }
if count > 0 { if count > 0 {
err.note(&format!( err.note(&format!(
@ -2260,8 +2263,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
)); ));
err.note(&format!( err.note(&format!(
"required because of the requirements on the impl of `{}` for `{}`", "required because of the requirements on the impl of `{}` for `{}`",
parent_trait_ref.print_only_trait_path(), parent_trait_pred.print_modifiers_and_trait_path(),
parent_trait_ref.skip_binder().self_ty() parent_trait_pred.skip_binder().self_ty()
)); ));
} }
// #74711: avoid a stack overflow // #74711: avoid a stack overflow
@ -2269,6 +2272,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
self.note_obligation_cause_code( self.note_obligation_cause_code(
err, err,
&parent_predicate, &parent_predicate,
param_env,
&data.parent_code, &data.parent_code,
obligated_types, obligated_types,
seen_requirements, seen_requirements,
@ -2276,13 +2280,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
}); });
} }
ObligationCauseCode::DerivedObligation(ref data) => { ObligationCauseCode::DerivedObligation(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 parent_predicate = parent_trait_ref.without_const().to_predicate(tcx); let parent_predicate = parent_trait_ref.to_predicate(tcx);
// #74711: avoid a stack overflow // #74711: avoid a stack overflow
ensure_sufficient_stack(|| { ensure_sufficient_stack(|| {
self.note_obligation_cause_code( self.note_obligation_cause_code(
err, err,
&parent_predicate, &parent_predicate,
param_env,
&data.parent_code, &data.parent_code,
obligated_types, obligated_types,
seen_requirements, seen_requirements,
@ -2336,6 +2341,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
self.note_obligation_cause_code( self.note_obligation_cause_code(
err, err,
predicate, predicate,
param_env,
&parent_code, &parent_code,
obligated_types, obligated_types,
seen_requirements, seen_requirements,
@ -2426,15 +2432,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
&self, &self,
err: &mut DiagnosticBuilder<'_>, err: &mut DiagnosticBuilder<'_>,
obligation: &PredicateObligation<'tcx>, obligation: &PredicateObligation<'tcx>,
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, trait_pred: ty::PolyTraitPredicate<'tcx>,
span: Span, span: Span,
) { ) {
debug!( 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, obligation,
span, span,
trait_ref, trait_pred,
trait_ref.self_ty() trait_pred.self_ty()
); );
let body_hir_id = obligation.cause.body_id; let body_hir_id = obligation.cause.body_id;
let item_id = self.tcx.hir().get_parent_node(body_hir_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 { if let Some(hir::GeneratorKind::Async(_)) = body.generator_kind {
let future_trait = self.tcx.require_lang_item(LangItem::Future, None); 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. // Do not check on infer_types to avoid panic in evaluate_obligation.
if self_ty.has_infer_types() { if self_ty.has_infer_types() {
@ -2464,7 +2470,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
let projection_ty = ty::ProjectionTy { let projection_ty = ty::ProjectionTy {
// `T` // `T`
substs: self.tcx.mk_substs_trait( 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), self.fresh_substs_for_item(span, item_def_id),
), ),
// `Future::Output` // `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( let try_obligation = self.mk_trait_obligation_with_new_self_ty(
obligation.param_env, obligation.param_env,
trait_ref, trait_pred,
normalized_ty, normalized_ty,
); );
debug!("suggest_await_before_try: try_trait_obligation {:?}", try_obligation); debug!("suggest_await_before_try: try_trait_obligation {:?}", try_obligation);

View file

@ -659,7 +659,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
_ => bug!("closure candidate for non-closure {:?}", obligation), _ => 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 } = let Normalized { value: obligation_predicate, mut obligations } =
ensure_sufficient_stack(|| { ensure_sufficient_stack(|| {
normalize_with_depth( normalize_with_depth(
@ -689,7 +689,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligations.extend(self.confirm_poly_trait_refs( obligations.extend(self.confirm_poly_trait_refs(
obligation.cause.clone(), obligation.cause.clone(),
obligation.param_env, obligation.param_env,
obligation_predicate, obligation_predicate.to_poly_trait_ref(),
trait_ref, trait_ref,
)?); )?);

View file

@ -2413,7 +2413,7 @@ impl<'tcx> TraitObligationExt<'tcx> for TraitObligation<'tcx> {
// chain. Ideally, we should have a way to configure this either // chain. Ideally, we should have a way to configure this either
// by using -Z verbose or just a CLI argument. // by using -Z verbose or just a CLI argument.
let derived_cause = DerivedObligationCause { let derived_cause = DerivedObligationCause {
parent_trait_ref: obligation.predicate.to_poly_trait_ref(), parent_trait_pred: obligation.predicate,
parent_code: obligation.cause.clone_code(), parent_code: obligation.cause.clone_code(),
}; };
let derived_code = variant(derived_cause); let derived_code = variant(derived_cause);

View file

@ -506,12 +506,21 @@ crate fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option<St
let mut pretty_predicates = let mut pretty_predicates =
Vec::with_capacity(predicates.len() + types_without_default_bounds.len()); Vec::with_capacity(predicates.len() + types_without_default_bounds.len());
for (p, _) in predicates { for (mut p, _) in predicates {
if let Some(poly_trait_ref) = p.to_opt_poly_trait_pred() { if let Some(poly_trait_ref) = p.to_opt_poly_trait_pred() {
if Some(poly_trait_ref.def_id()) == sized_trait { if Some(poly_trait_ref.def_id()) == sized_trait {
types_without_default_bounds.remove(poly_trait_ref.self_ty().skip_binder()); types_without_default_bounds.remove(poly_trait_ref.self_ty().skip_binder());
continue; continue;
} }
if ty::BoundConstness::ConstIfConst == poly_trait_ref.skip_binder().constness {
let new_trait_pred = poly_trait_ref.map_bound(|mut trait_pred| {
trait_pred.constness = ty::BoundConstness::NotConst;
trait_pred
});
p = tcx.mk_predicate(new_trait_pred.map_bound(ty::PredicateKind::Trait))
}
} }
pretty_predicates.push(p.to_string()); pretty_predicates.push(p.to_string());
} }

View file

@ -306,10 +306,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
let extend = |obligation: traits::PredicateObligation<'tcx>| { let extend = |obligation: traits::PredicateObligation<'tcx>| {
let mut cause = cause.clone(); 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 { let derived_cause = traits::DerivedObligationCause {
// FIXME(fee1-dead): when improving error messages, change this to PolyTraitPredicate parent_trait_pred,
parent_trait_ref: parent_trait_ref.map_bound(|t| t.trait_ref),
parent_code: obligation.cause.clone_code(), parent_code: obligation.cause.clone_code(),
}; };
*cause.make_mut_code() = *cause.make_mut_code() =

View file

@ -1021,7 +1021,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ObligationCauseCode::BuiltinDerivedObligation(code) | ObligationCauseCode::BuiltinDerivedObligation(code) |
ObligationCauseCode::ImplDerivedObligation(code) | ObligationCauseCode::ImplDerivedObligation(code) |
ObligationCauseCode::DerivedObligation(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) = _ if let ty::PredicateKind::Trait(predicate) =
error.obligation.predicate.kind().skip_binder() => { error.obligation.predicate.kind().skip_binder() => {

View file

@ -823,9 +823,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => None, _ => 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 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 tr_self_ty = parent_trait_ref.skip_binder().self_ty();
let mut candidates = vec![]; let mut candidates = vec![];
self.tcx.for_each_relevant_impl( self.tcx.for_each_relevant_impl(

View file

@ -16,8 +16,8 @@ impl !Drop for NonDrop {}
fn main() { fn main() {
const { const {
f(UnconstDrop); f(UnconstDrop);
//~^ ERROR the trait bound `UnconstDrop: Drop` is not satisfied //~^ ERROR the trait bound `UnconstDrop: ~const Drop` is not satisfied
f(NonDrop); f(NonDrop);
//~^ ERROR the trait bound `NonDrop: Drop` is not satisfied //~^ ERROR the trait bound `NonDrop: ~const Drop` is not satisfied
} }
} }

View file

@ -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 --> $DIR/const-block-const-bound.rs:18:11
| |
LL | f(UnconstDrop); 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 | required by a bound introduced by this call
| |
@ -11,16 +11,18 @@ note: required by a bound in `f`
| |
LL | const fn f<T: ~const Drop>(x: T) {} LL | const fn f<T: ~const Drop>(x: T) {}
| ^^^^^^^^^^^ required by this bound in `f` | ^^^^^^^^^^^ 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 --> $DIR/const-block-const-bound.rs:20:11
| |
LL | f(NonDrop); 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 | required by a bound introduced by this call
| |
@ -29,6 +31,12 @@ note: required by a bound in `f`
| |
LL | const fn f<T: ~const Drop>(x: T) {} LL | const fn f<T: ~const Drop>(x: T) {}
| ^^^^^^^^^^^ required by this bound in `f` | ^^^^^^^^^^^ required by this bound in `f`
help: consider borrowing here
|
LL | f(&NonDrop);
| +
LL | f(&mut NonDrop);
| ++++
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -4,9 +4,9 @@ use std::intrinsics::const_eval_select;
const fn not_fn_items() { const fn not_fn_items() {
const_eval_select((), || {}, || {}); const_eval_select((), || {}, || {});
//~^ ERROR expected a `FnOnce<()>` closure //~^ ERROR the trait bound
const_eval_select((), 42, 0xDEADBEEF); const_eval_select((), 42, 0xDEADBEEF);
//~^ ERROR expected a `FnOnce<()>` closure //~^ ERROR the trait bound
//~| ERROR expected a `FnOnce<()>` closure //~| ERROR expected a `FnOnce<()>` closure
} }

View file

@ -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 --> $DIR/const-eval-select-bad.rs:6:27
| |
LL | const_eval_select((), || {}, || {}); LL | const_eval_select((), || {}, || {});
@ -6,7 +6,7 @@ LL | const_eval_select((), || {}, || {});
| | | |
| required by a bound introduced by this call | 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: 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` note: required by a bound in `const_eval_select`
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL --> $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<ARG, Output = RET>, LL | F: ~const FnOnce<ARG, Output = RET>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 --> $DIR/const-eval-select-bad.rs:8:27
| |
LL | const_eval_select((), 42, 0xDEADBEEF); LL | const_eval_select((), 42, 0xDEADBEEF);
@ -22,7 +22,7 @@ LL | const_eval_select((), 42, 0xDEADBEEF);
| | | |
| required by a bound introduced by this call | 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: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
note: required by a bound in `const_eval_select` note: required by a bound in `const_eval_select`
--> $SRC_DIR/core/src/intrinsics.rs:LL:COL --> $SRC_DIR/core/src/intrinsics.rs:LL:COL

View file

@ -1,5 +1,5 @@
// FIXME(fee1-dead): this should have a better error message
#![feature(const_trait_impl)] #![feature(const_trait_impl)]
struct NonConstAdd(i32); struct NonConstAdd(i32);
impl std::ops::Add for NonConstAdd { impl std::ops::Add for NonConstAdd {
@ -16,7 +16,7 @@ trait Foo {
impl const Foo for NonConstAdd { impl const Foo for NonConstAdd {
type Bar = NonConstAdd; type Bar = NonConstAdd;
//~^ ERROR //~^ ERROR: the trait bound `NonConstAdd: ~const Add` is not satisfied
} }
trait Baz { trait Baz {

View file

@ -1,10 +1,10 @@
error[E0277]: cannot add `NonConstAdd` to `NonConstAdd` error[E0277]: the trait bound `NonConstAdd: ~const Add` is not satisfied
--> $DIR/assoc-type.rs:18:16 --> $DIR/assoc-type.rs:18:16
| |
LL | type Bar = NonConstAdd; LL | type Bar = NonConstAdd;
| ^^^^^^^^^^^ no implementation for `NonConstAdd + 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` note: required by a bound in `Foo::Bar`
--> $DIR/assoc-type.rs:14:15 --> $DIR/assoc-type.rs:14:15
| |
@ -12,8 +12,8 @@ LL | type Bar: ~const std::ops::Add;
| ^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::Bar` | ^^^^^^^^^^^^^^^^^^^^ 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 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 error: aborting due to previous error

View file

@ -1,4 +1,4 @@
error[E0277]: can't compare `S` with `S` error[E0277]: the trait bound `S: ~const PartialEq` is not satisfied
--> $DIR/call-generic-method-nonconst.rs:19:34 --> $DIR/call-generic-method-nonconst.rs:19:34
| |
LL | pub const EQ: bool = equals_self(&S); 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 | 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` note: required by a bound in `equals_self`
--> $DIR/call-generic-method-nonconst.rs:12:25 --> $DIR/call-generic-method-nonconst.rs:12:25
| |

View file

@ -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 --> $DIR/const-drop-fail.rs:44:5
| |
LL | const _: () = check($exp); LL | const _: () = check($exp);
| ----- required by a bound introduced by this call | ----- required by a bound introduced by this call
... ...
LL | NonTrivialDrop, LL | NonTrivialDrop,
| ^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `NonTrivialDrop` | ^^^^^^^^^^^^^^ expected an implementor of trait `~const Drop`
| |
note: required by a bound in `check` note: required by a bound in `check`
--> $DIR/const-drop-fail.rs:35:19 --> $DIR/const-drop-fail.rs:35:19
| |
LL | const fn check<T: ~const Drop>(_: T) {} LL | const fn check<T: ~const Drop>(_: T) {}
| ^^^^^^^^^^^ required by this bound in `check` | ^^^^^^^^^^^ 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 --> $DIR/const-drop-fail.rs:46:5
| |
LL | const _: () = check($exp); LL | const _: () = check($exp);
| ----- required by a bound introduced by this call | ----- required by a bound introduced by this call
... ...
LL | ConstImplWithDropGlue(NonTrivialDrop), 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` note: required because it appears within the type `ConstImplWithDropGlue`
--> $DIR/const-drop-fail.rs:17:8 --> $DIR/const-drop-fail.rs:17:8
@ -33,16 +39,16 @@ note: required by a bound in `check`
LL | const fn check<T: ~const Drop>(_: T) {} LL | const fn check<T: ~const Drop>(_: T) {}
| ^^^^^^^^^^^ required by this bound in `check` | ^^^^^^^^^^^ required by this bound in `check`
error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: ~const Drop` is not satisfied
--> $DIR/const-drop-fail.rs:48:5 --> $DIR/const-drop-fail.rs:48:5
| |
LL | const _: () = check($exp); LL | const _: () = check($exp);
| ----- required by a bound introduced by this call | ----- required by a bound introduced by this call
... ...
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData), LL | ConstDropImplWithBounds::<NonTrivialDrop>(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<NonTrivialDrop>` note: required because of the requirements on the impl of `~const Drop` for `ConstDropImplWithBounds<NonTrivialDrop>`
--> $DIR/const-drop-fail.rs:29:25 --> $DIR/const-drop-fail.rs:29:25
| |
LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> { LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
@ -52,6 +58,12 @@ note: required by a bound in `check`
| |
LL | const fn check<T: ~const Drop>(_: T) {} LL | const fn check<T: ~const Drop>(_: T) {}
| ^^^^^^^^^^^ required by this bound in `check` | ^^^^^^^^^^^ required by this bound in `check`
help: consider borrowing here
|
LL | &ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
| +
LL | &mut ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
| ++++
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -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 --> $DIR/const-drop-fail.rs:44:5
| |
LL | const _: () = check($exp); LL | const _: () = check($exp);
| ----- required by a bound introduced by this call | ----- required by a bound introduced by this call
... ...
LL | NonTrivialDrop, LL | NonTrivialDrop,
| ^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `NonTrivialDrop` | ^^^^^^^^^^^^^^ expected an implementor of trait `~const Drop`
| |
note: required by a bound in `check` note: required by a bound in `check`
--> $DIR/const-drop-fail.rs:35:19 --> $DIR/const-drop-fail.rs:35:19
| |
LL | const fn check<T: ~const Drop>(_: T) {} LL | const fn check<T: ~const Drop>(_: T) {}
| ^^^^^^^^^^^ required by this bound in `check` | ^^^^^^^^^^^ 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 --> $DIR/const-drop-fail.rs:46:5
| |
LL | const _: () = check($exp); LL | const _: () = check($exp);
| ----- required by a bound introduced by this call | ----- required by a bound introduced by this call
... ...
LL | ConstImplWithDropGlue(NonTrivialDrop), 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` note: required because it appears within the type `ConstImplWithDropGlue`
--> $DIR/const-drop-fail.rs:17:8 --> $DIR/const-drop-fail.rs:17:8
@ -33,16 +39,16 @@ note: required by a bound in `check`
LL | const fn check<T: ~const Drop>(_: T) {} LL | const fn check<T: ~const Drop>(_: T) {}
| ^^^^^^^^^^^ required by this bound in `check` | ^^^^^^^^^^^ required by this bound in `check`
error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: ~const Drop` is not satisfied
--> $DIR/const-drop-fail.rs:48:5 --> $DIR/const-drop-fail.rs:48:5
| |
LL | const _: () = check($exp); LL | const _: () = check($exp);
| ----- required by a bound introduced by this call | ----- required by a bound introduced by this call
... ...
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData), LL | ConstDropImplWithBounds::<NonTrivialDrop>(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<NonTrivialDrop>` note: required because of the requirements on the impl of `~const Drop` for `ConstDropImplWithBounds<NonTrivialDrop>`
--> $DIR/const-drop-fail.rs:29:25 --> $DIR/const-drop-fail.rs:29:25
| |
LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> { LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
@ -52,6 +58,12 @@ note: required by a bound in `check`
| |
LL | const fn check<T: ~const Drop>(_: T) {} LL | const fn check<T: ~const Drop>(_: T) {}
| ^^^^^^^^^^^ required by this bound in `check` | ^^^^^^^^^^^ required by this bound in `check`
help: consider borrowing here
|
LL | &ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
| +
LL | &mut ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
| ++++
error: aborting due to 3 previous errors error: aborting due to 3 previous errors

View file

@ -10,7 +10,7 @@ pub trait Foo {
#[default_method_body_is_const] #[default_method_body_is_const]
fn foo() { fn foo() {
foo::<()>(); foo::<()>();
//~^ ERROR the trait bound `(): Tr` is not satisfied //~^ ERROR the trait bound `(): ~const Tr` is not satisfied
} }
} }

View file

@ -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 --> $DIR/default-method-body-is-const-body-checking.rs:12:15
| |
LL | foo::<()>(); LL | foo::<()>();
| ^^ the trait `Tr` is not implemented for `()` | ^^ the trait `~const Tr` is not implemented for `()`
| |
note: required by a bound in `foo` note: required by a bound in `foo`
--> $DIR/default-method-body-is-const-body-checking.rs:7:28 --> $DIR/default-method-body-is-const-body-checking.rs:7:28
@ -11,8 +11,8 @@ LL | const fn foo<T>() where T: ~const Tr {}
| ^^^^^^^^^ required by this bound in `foo` | ^^^^^^^^^ required by this bound in `foo`
help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement 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 error: aborting due to previous error

View file

@ -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 --> $DIR/trait-where-clause.rs:14:5
| |
LL | T::b(); 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` note: required by a bound in `Foo::b`
--> $DIR/trait-where-clause.rs:8:24 --> $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` | ^^^^^^^^^^ required by this bound in `Foo::b`
help: consider further restricting this bound help: consider further restricting this bound
| |
LL | const fn test1<T: ~const Foo + Bar + Bar>() { LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() {
| +++++ | ++++++++++++
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 --> $DIR/trait-where-clause.rs:16:5
| |
LL | T::c::<T>(); LL | T::c::<T>();
| ^^^^^^^^^ 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` note: required by a bound in `Foo::c`
--> $DIR/trait-where-clause.rs:9:13 --> $DIR/trait-where-clause.rs:9:13
@ -27,8 +27,8 @@ LL | fn c<T: ~const Bar>();
| ^^^^^^^^^^ required by this bound in `Foo::c` | ^^^^^^^^^^ required by this bound in `Foo::c`
help: consider further restricting this bound help: consider further restricting this bound
| |
LL | const fn test1<T: ~const Foo + Bar + Bar>() { LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() {
| +++++ | ++++++++++++
error[E0277]: the trait bound `T: Bar` is not satisfied error[E0277]: the trait bound `T: Bar` is not satisfied
--> $DIR/trait-where-clause.rs:28:5 --> $DIR/trait-where-clause.rs:28:5