Rollup merge of #92256 - fee1-dead:improve-selection-err, r=oli-obk

Improve selection errors for `~const` trait bounds
This commit is contained in:
Matthias Krüger 2022-01-26 23:45:22 +01:00 committed by GitHub
commit e2b2bfe10c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 428 additions and 218 deletions

View File

@ -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<ObligationCauseCode<'tcx>>,

View File

@ -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)]

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! {
Ty<'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, 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<'tcx>, 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> {

View File

@ -321,6 +321,7 @@ symbols! {
and,
and_then,
any,
append_const_msg,
arbitrary_enum_discriminant,
arbitrary_self_types,
arith_offset,

View File

@ -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>;
@ -1541,7 +1578,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
) -> Option<(String, Option<Span>)> {
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 => {
@ -1594,21 +1631,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")]
@ -2009,6 +2045,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(),
@ -2156,7 +2193,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;

View File

@ -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<Span>;
@ -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>, Span, Option<hir::HirId>, Option<Span>)>,
inner_generator_body: Option<&hir::Body<'tcx>>,
outer_generator: Option<DefId>,
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<DefId>,
@ -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 `<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 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,
&param_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, &param_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<dyn Trait>`.
@ -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>, Span, Option<hir::HirId>, Option<Span>)>,
inner_generator_body: Option<&hir::Body<'tcx>>,
outer_generator: Option<DefId>,
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<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`");
}
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);

View File

@ -19,6 +19,7 @@ pub struct OnUnimplementedDirective {
pub label: Option<OnUnimplementedFormatString>,
pub note: Option<OnUnimplementedFormatString>,
pub enclosing_scope: Option<OnUnimplementedFormatString>,
pub append_const_msg: Option<Option<Symbol>>,
}
#[derive(Default)]
@ -27,6 +28,11 @@ pub struct OnUnimplementedNote {
pub label: Option<String>,
pub note: Option<String>,
pub enclosing_scope: Option<String>,
/// 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<Option<Symbol>>,
}
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<Symbol, String> =
@ -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,
}
}
}

View File

@ -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,
)?);

View File

@ -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);

View File

@ -506,12 +506,21 @@ crate fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option<St
let mut pretty_predicates =
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 Some(poly_trait_ref.def_id()) == sized_trait {
types_without_default_bounds.remove(poly_trait_ref.self_ty().skip_binder());
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());
}

View File

@ -306,10 +306,9 @@ impl<'a, 'tcx> 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() =

View File

@ -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() => {

View File

@ -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(

View File

@ -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<Rhs: ?Sized = Self> {
@ -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<Rhs: ?Sized = Self>: PartialEq<Rhs> {

View File

@ -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<Rhs = Self> {

View File

@ -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
}
}

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
|
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<T: ~const Drop>(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<T: ~const Drop>(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

View File

@ -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
}

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
|
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<ARG, Output = RET>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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

View File

@ -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 {

View File

@ -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

View File

@ -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
|

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
|
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: ~const Drop>(_: 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: ~const Drop>(_: T) {}
| ^^^^^^^^^^^ 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
|
LL | const _: () = check($exp);
| ----- required by a bound introduced by this call
...
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
|
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) {}
| ^^^^^^^^^^^ 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

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
|
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: ~const Drop>(_: 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: ~const Drop>(_: T) {}
| ^^^^^^^^^^^ 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
|
LL | const _: () = check($exp);
| ----- required by a bound introduced by this call
...
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
|
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) {}
| ^^^^^^^^^^^ 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

View File

@ -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
}
}

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
|
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<T>() 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

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
|
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<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
|
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`
--> $DIR/trait-where-clause.rs:9:13
@ -27,8 +27,8 @@ LL | fn c<T: ~const Bar>();
| ^^^^^^^^^^ required by this bound in `Foo::c`
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
--> $DIR/trait-where-clause.rs:28:5