mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Rollup merge of #92256 - fee1-dead:improve-selection-err, r=oli-obk
Improve selection errors for `~const` trait bounds
This commit is contained in:
commit
e2b2bfe10c
@ -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>>,
|
||||
|
@ -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)]
|
||||
|
@ -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> {
|
||||
|
@ -321,6 +321,7 @@ symbols! {
|
||||
and,
|
||||
and_then,
|
||||
any,
|
||||
append_const_msg,
|
||||
arbitrary_enum_discriminant,
|
||||
arbitrary_self_types,
|
||||
arith_offset,
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
¶m_name,
|
||||
&constraint,
|
||||
Some(trait_ref.def_id()),
|
||||
Some(trait_pred.def_id()),
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@ -471,7 +473,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
}) if !param_ty => {
|
||||
// Missing generic type parameter bound.
|
||||
let param_name = self_ty.to_string();
|
||||
let constraint = trait_ref.print_only_trait_path().to_string();
|
||||
let constraint = trait_pred.print_modifiers_and_trait_path().to_string();
|
||||
if suggest_arbitrary_trait_bound(generics, &mut err, ¶m_name, &constraint) {
|
||||
return;
|
||||
}
|
||||
@ -492,7 +494,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
err: &mut DiagnosticBuilder<'tcx>,
|
||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
) {
|
||||
// It only make sense when suggesting dereferences for arguments
|
||||
let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } =
|
||||
@ -505,13 +507,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
let param_env = obligation.param_env;
|
||||
let body_id = obligation.cause.body_id;
|
||||
let span = obligation.cause.span;
|
||||
let real_trait_ref = match &*code {
|
||||
let real_trait_pred = match &*code {
|
||||
ObligationCauseCode::ImplDerivedObligation(cause)
|
||||
| ObligationCauseCode::DerivedObligation(cause)
|
||||
| ObligationCauseCode::BuiltinDerivedObligation(cause) => cause.parent_trait_ref,
|
||||
_ => trait_ref,
|
||||
| ObligationCauseCode::BuiltinDerivedObligation(cause) => cause.parent_trait_pred,
|
||||
_ => trait_pred,
|
||||
};
|
||||
let real_ty = match real_trait_ref.self_ty().no_bound_vars() {
|
||||
let real_ty = match real_trait_pred.self_ty().no_bound_vars() {
|
||||
Some(ty) => ty,
|
||||
None => return,
|
||||
};
|
||||
@ -522,7 +524,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
// Re-add the `&`
|
||||
let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl });
|
||||
let obligation =
|
||||
self.mk_trait_obligation_with_new_self_ty(param_env, real_trait_ref, ty);
|
||||
self.mk_trait_obligation_with_new_self_ty(param_env, real_trait_pred, ty);
|
||||
Some(steps).filter(|_| self.predicate_may_hold(&obligation))
|
||||
}) {
|
||||
if steps > 0 {
|
||||
@ -589,9 +591,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
|
||||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
) {
|
||||
let self_ty = match trait_ref.self_ty().no_bound_vars() {
|
||||
let self_ty = match trait_pred.self_ty().no_bound_vars() {
|
||||
None => return,
|
||||
Some(ty) => ty,
|
||||
};
|
||||
@ -611,7 +613,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
};
|
||||
|
||||
let new_obligation =
|
||||
self.mk_trait_obligation_with_new_self_ty(obligation.param_env, trait_ref, output_ty);
|
||||
self.mk_trait_obligation_with_new_self_ty(obligation.param_env, trait_pred, output_ty);
|
||||
|
||||
match self.evaluate_obligation(&new_obligation) {
|
||||
Ok(
|
||||
@ -682,7 +684,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
poly_trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>,
|
||||
poly_trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
has_custom_message: bool,
|
||||
) -> bool {
|
||||
let span = obligation.cause.span;
|
||||
@ -715,24 +717,18 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
let param_env = obligation.param_env;
|
||||
|
||||
// Try to apply the original trait binding obligation by borrowing.
|
||||
let mut try_borrowing = |old_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
|
||||
let mut try_borrowing = |old_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
blacklist: &[DefId]|
|
||||
-> bool {
|
||||
if blacklist.contains(&old_ref.def_id()) {
|
||||
if blacklist.contains(&old_pred.def_id()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let orig_ty = old_ref.self_ty().skip_binder();
|
||||
let orig_ty = old_pred.self_ty().skip_binder();
|
||||
let mk_result = |new_ty| {
|
||||
let new_ref = old_ref.rebind(ty::TraitRef::new(
|
||||
old_ref.def_id(),
|
||||
self.tcx.mk_substs_trait(new_ty, &old_ref.skip_binder().substs[1..]),
|
||||
));
|
||||
self.predicate_must_hold_modulo_regions(&Obligation::new(
|
||||
ObligationCause::dummy(),
|
||||
param_env,
|
||||
new_ref.without_const().to_predicate(self.tcx),
|
||||
))
|
||||
let obligation =
|
||||
self.mk_trait_obligation_with_new_self_ty(param_env, old_pred, new_ty);
|
||||
self.predicate_must_hold_modulo_regions(&obligation)
|
||||
};
|
||||
let imm_result = mk_result(self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, orig_ty));
|
||||
let mut_result = mk_result(self.tcx.mk_mut_ref(self.tcx.lifetimes.re_static, orig_ty));
|
||||
@ -748,7 +744,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
let msg = format!(
|
||||
"the trait bound `{}: {}` is not satisfied",
|
||||
orig_ty,
|
||||
old_ref.print_only_trait_path(),
|
||||
old_pred.print_modifiers_and_trait_path(),
|
||||
);
|
||||
if has_custom_message {
|
||||
err.note(&msg);
|
||||
@ -764,7 +760,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
span,
|
||||
&format!(
|
||||
"expected an implementor of trait `{}`",
|
||||
old_ref.print_only_trait_path(),
|
||||
old_pred.print_modifiers_and_trait_path(),
|
||||
),
|
||||
);
|
||||
|
||||
@ -806,11 +802,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
};
|
||||
|
||||
if let ObligationCauseCode::ImplDerivedObligation(obligation) = code {
|
||||
try_borrowing(obligation.parent_trait_ref, &[])
|
||||
try_borrowing(obligation.parent_trait_pred, &[])
|
||||
} else if let ObligationCauseCode::BindingObligation(_, _)
|
||||
| ObligationCauseCode::ItemObligation(_) = code
|
||||
{
|
||||
try_borrowing(*poly_trait_ref, &never_suggest_borrow)
|
||||
try_borrowing(poly_trait_pred, &never_suggest_borrow)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@ -822,7 +818,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
|
||||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
) {
|
||||
let span = obligation.cause.span;
|
||||
|
||||
@ -834,7 +830,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut suggested_ty = match trait_ref.self_ty().no_bound_vars() {
|
||||
let mut suggested_ty = match trait_pred.self_ty().no_bound_vars() {
|
||||
Some(ty) => ty,
|
||||
None => return,
|
||||
};
|
||||
@ -847,7 +843,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
|
||||
let new_obligation = self.mk_trait_obligation_with_new_self_ty(
|
||||
obligation.param_env,
|
||||
trait_ref,
|
||||
trait_pred,
|
||||
suggested_ty,
|
||||
);
|
||||
|
||||
@ -941,7 +937,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
&self,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
|
||||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
) {
|
||||
let points_at_arg = matches!(
|
||||
obligation.cause.code(),
|
||||
@ -956,14 +952,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
// Do not suggest removal of borrow from type arguments.
|
||||
return;
|
||||
}
|
||||
let trait_ref = self.resolve_vars_if_possible(trait_ref);
|
||||
if trait_ref.has_infer_types_or_consts() {
|
||||
let trait_pred = self.resolve_vars_if_possible(trait_pred);
|
||||
if trait_pred.has_infer_types_or_consts() {
|
||||
// Do not ICE while trying to find if a reborrow would succeed on a trait with
|
||||
// unresolved bindings.
|
||||
return;
|
||||
}
|
||||
|
||||
if let ty::Ref(region, t_type, mutability) = *trait_ref.skip_binder().self_ty().kind() {
|
||||
if let ty::Ref(region, t_type, mutability) = *trait_pred.skip_binder().self_ty().kind()
|
||||
{
|
||||
if region.is_late_bound() || t_type.has_escaping_bound_vars() {
|
||||
// Avoid debug assertion in `mk_obligation_for_def_id`.
|
||||
//
|
||||
@ -980,7 +977,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
|
||||
let new_obligation = self.mk_trait_obligation_with_new_self_ty(
|
||||
obligation.param_env,
|
||||
trait_ref,
|
||||
trait_pred,
|
||||
suggested_ty,
|
||||
);
|
||||
let suggested_ty_would_satisfy_obligation = self
|
||||
@ -1002,9 +999,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
} else {
|
||||
err.note(&format!(
|
||||
"`{}` is implemented for `{:?}`, but not for `{:?}`",
|
||||
trait_ref.print_only_trait_path(),
|
||||
trait_pred.print_modifiers_and_trait_path(),
|
||||
suggested_ty,
|
||||
trait_ref.skip_binder().self_ty(),
|
||||
trait_pred.skip_binder().self_ty(),
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -1017,7 +1014,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
span: Span,
|
||||
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
|
||||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
) {
|
||||
let is_empty_tuple =
|
||||
|ty: ty::Binder<'tcx, Ty<'_>>| *ty.skip_binder().kind() == ty::Tuple(ty::List::empty());
|
||||
@ -1033,7 +1030,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
if let hir::ExprKind::Block(blk, _) = &body.value.kind {
|
||||
if sig.decl.output.span().overlaps(span)
|
||||
&& blk.expr.is_none()
|
||||
&& is_empty_tuple(trait_ref.self_ty())
|
||||
&& is_empty_tuple(trait_pred.self_ty())
|
||||
{
|
||||
// FIXME(estebank): When encountering a method with a trait
|
||||
// bound not satisfied in the return type with a body that has
|
||||
@ -1069,7 +1066,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
span: Span,
|
||||
obligation: &PredicateObligation<'tcx>,
|
||||
trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
|
||||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
) -> bool {
|
||||
match obligation.cause.code().peel_derives() {
|
||||
// Only suggest `impl Trait` if the return type is unsized because it is `dyn Trait`.
|
||||
@ -1088,8 +1085,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||
return false;
|
||||
};
|
||||
let body = hir.body(*body_id);
|
||||
let trait_ref = self.resolve_vars_if_possible(trait_ref);
|
||||
let ty = trait_ref.skip_binder().self_ty();
|
||||
let trait_pred = self.resolve_vars_if_possible(trait_pred);
|
||||
let ty = trait_pred.skip_binder().self_ty();
|
||||
let is_object_safe = match ty.kind() {
|
||||
ty::Dynamic(predicates, _) => {
|
||||
// If the `dyn Trait` is not object safe, do not suggest `Box<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);
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
)?);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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() =
|
||||
|
@ -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() => {
|
||||
|
@ -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(
|
||||
|
@ -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> {
|
||||
|
@ -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> {
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user