Rollup merge of #132345 - compiler-errors:fx-diag, r=lcnr
Improve diagnostics for `HostEffectPredicate` in the new solver Adds derived cause for host effect predicates. Some diagnostics regress, but that's connected to the fact that our predicate visitor doesn't play well with aliases just yet.
This commit is contained in:
commit
b642740e4f
14 changed files with 284 additions and 41 deletions
|
@ -125,6 +125,15 @@ impl<'tcx> ObligationCause<'tcx> {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn derived_host_cause(
|
||||
mut self,
|
||||
parent_host_pred: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
|
||||
variant: impl FnOnce(DerivedHostCause<'tcx>) -> ObligationCauseCode<'tcx>,
|
||||
) -> ObligationCause<'tcx> {
|
||||
self.code = variant(DerivedHostCause { parent_host_pred, parent_code: self.code }).into();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn to_constraint_category(&self) -> ConstraintCategory<'tcx> {
|
||||
match self.code() {
|
||||
ObligationCauseCode::MatchImpl(cause, _) => cause.to_constraint_category(),
|
||||
|
@ -278,6 +287,14 @@ pub enum ObligationCauseCode<'tcx> {
|
|||
/// Derived obligation for WF goals.
|
||||
WellFormedDerived(DerivedCause<'tcx>),
|
||||
|
||||
/// Derived obligation (i.e. `where` clause) on an user-provided impl
|
||||
/// or a trait alias.
|
||||
ImplDerivedHost(Box<ImplDerivedHostCause<'tcx>>),
|
||||
|
||||
/// Derived obligation (i.e. `where` clause) on an user-provided impl
|
||||
/// or a trait alias.
|
||||
BuiltinDerivedHost(DerivedHostCause<'tcx>),
|
||||
|
||||
/// Derived obligation refined to point at a specific argument in
|
||||
/// a call or method expression.
|
||||
FunctionArg {
|
||||
|
@ -437,36 +454,38 @@ pub enum WellFormedLoc {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
|
||||
#[derive(TypeVisitable, TypeFoldable)]
|
||||
pub struct ImplDerivedCause<'tcx> {
|
||||
pub derived: DerivedCause<'tcx>,
|
||||
/// The `DefId` of the `impl` that gave rise to the `derived` obligation.
|
||||
/// If the `derived` obligation arose from a trait alias, which conceptually has a synthetic impl,
|
||||
/// then this will be the `DefId` of that trait alias. Care should therefore be taken to handle
|
||||
/// that exceptional case where appropriate.
|
||||
pub impl_or_alias_def_id: DefId,
|
||||
/// The index of the derived predicate in the parent impl's predicates.
|
||||
pub impl_def_predicate_index: Option<usize>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'tcx> ObligationCauseCode<'tcx> {
|
||||
/// Returns the base obligation, ignoring derived obligations.
|
||||
pub fn peel_derives(&self) -> &Self {
|
||||
let mut base_cause = self;
|
||||
while let Some((parent_code, _)) = base_cause.parent() {
|
||||
while let Some(parent_code) = base_cause.parent() {
|
||||
base_cause = parent_code;
|
||||
}
|
||||
base_cause
|
||||
}
|
||||
|
||||
pub fn parent(&self) -> Option<&Self> {
|
||||
match self {
|
||||
ObligationCauseCode::FunctionArg { parent_code, .. } => Some(parent_code),
|
||||
ObligationCauseCode::BuiltinDerived(derived)
|
||||
| ObligationCauseCode::WellFormedDerived(derived)
|
||||
| ObligationCauseCode::ImplDerived(box ImplDerivedCause { derived, .. }) => {
|
||||
Some(&derived.parent_code)
|
||||
}
|
||||
ObligationCauseCode::BuiltinDerivedHost(derived)
|
||||
| ObligationCauseCode::ImplDerivedHost(box ImplDerivedHostCause { derived, .. }) => {
|
||||
Some(&derived.parent_code)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the base obligation and the base trait predicate, if any, ignoring
|
||||
/// derived obligations.
|
||||
pub fn peel_derives_with_predicate(&self) -> (&Self, Option<ty::PolyTraitPredicate<'tcx>>) {
|
||||
let mut base_cause = self;
|
||||
let mut base_trait_pred = None;
|
||||
while let Some((parent_code, parent_pred)) = base_cause.parent() {
|
||||
while let Some((parent_code, parent_pred)) = base_cause.parent_with_predicate() {
|
||||
base_cause = parent_code;
|
||||
if let Some(parent_pred) = parent_pred {
|
||||
base_trait_pred = Some(parent_pred);
|
||||
|
@ -476,7 +495,7 @@ impl<'tcx> ObligationCauseCode<'tcx> {
|
|||
(base_cause, base_trait_pred)
|
||||
}
|
||||
|
||||
pub fn parent(&self) -> Option<(&Self, Option<ty::PolyTraitPredicate<'tcx>>)> {
|
||||
pub fn parent_with_predicate(&self) -> Option<(&Self, Option<ty::PolyTraitPredicate<'tcx>>)> {
|
||||
match self {
|
||||
ObligationCauseCode::FunctionArg { parent_code, .. } => Some((parent_code, None)),
|
||||
ObligationCauseCode::BuiltinDerived(derived)
|
||||
|
@ -573,6 +592,42 @@ pub struct DerivedCause<'tcx> {
|
|||
pub parent_code: InternedObligationCauseCode<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
|
||||
#[derive(TypeVisitable, TypeFoldable)]
|
||||
pub struct ImplDerivedCause<'tcx> {
|
||||
pub derived: DerivedCause<'tcx>,
|
||||
/// The `DefId` of the `impl` that gave rise to the `derived` obligation.
|
||||
/// If the `derived` obligation arose from a trait alias, which conceptually has a synthetic impl,
|
||||
/// then this will be the `DefId` of that trait alias. Care should therefore be taken to handle
|
||||
/// that exceptional case where appropriate.
|
||||
pub impl_or_alias_def_id: DefId,
|
||||
/// The index of the derived predicate in the parent impl's predicates.
|
||||
pub impl_def_predicate_index: Option<usize>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
|
||||
#[derive(TypeVisitable, TypeFoldable)]
|
||||
pub struct DerivedHostCause<'tcx> {
|
||||
/// 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 predicate here
|
||||
/// directly.
|
||||
pub parent_host_pred: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
|
||||
|
||||
/// The parent trait had this cause.
|
||||
pub parent_code: InternedObligationCauseCode<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
|
||||
#[derive(TypeVisitable, TypeFoldable)]
|
||||
pub struct ImplDerivedHostCause<'tcx> {
|
||||
pub derived: DerivedHostCause<'tcx>,
|
||||
/// The `DefId` of the `impl` that gave rise to the `derived` obligation.
|
||||
pub impl_def_id: DefId,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, TypeVisitable)]
|
||||
pub enum SelectionError<'tcx> {
|
||||
/// The trait is not implemented.
|
||||
|
|
|
@ -634,6 +634,28 @@ impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyProjectionPredicate<'tcx>> for Clause<'t
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>>
|
||||
for Predicate<'tcx>
|
||||
{
|
||||
fn upcast_from(
|
||||
from: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) -> Self {
|
||||
from.map_bound(ty::ClauseKind::HostEffect).upcast(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>>
|
||||
for Clause<'tcx>
|
||||
{
|
||||
fn upcast_from(
|
||||
from: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) -> Self {
|
||||
from.map_bound(ty::ClauseKind::HostEffect).upcast(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> UpcastFrom<TyCtxt<'tcx>, NormalizesTo<'tcx>> for Predicate<'tcx> {
|
||||
fn upcast_from(from: NormalizesTo<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
|
||||
PredicateKind::NormalizesTo(from).upcast(tcx)
|
||||
|
|
|
@ -103,7 +103,7 @@ where
|
|||
|ecx| {
|
||||
// Const conditions must hold for the implied const bound to hold.
|
||||
ecx.add_goals(
|
||||
GoalSource::Misc,
|
||||
GoalSource::AliasBoundConstCondition,
|
||||
cx.const_conditions(alias_ty.def_id)
|
||||
.iter_instantiated(cx, alias_ty.args)
|
||||
.map(|trait_ref| {
|
||||
|
@ -353,7 +353,7 @@ where
|
|||
|
||||
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
|
||||
ecx.add_goals(
|
||||
GoalSource::Misc,
|
||||
GoalSource::AliasBoundConstCondition,
|
||||
const_conditions.into_iter().map(|trait_ref| {
|
||||
goal.with(
|
||||
cx,
|
||||
|
|
|
@ -737,7 +737,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
applied_do_not_recommend = true;
|
||||
}
|
||||
}
|
||||
if let Some((parent_cause, _parent_pred)) = base_cause.parent() {
|
||||
if let Some(parent_cause) = base_cause.parent() {
|
||||
base_cause = parent_cause.clone();
|
||||
} else {
|
||||
break;
|
||||
|
@ -797,7 +797,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
trait_ref.skip_binder().args.type_at(1).to_opt_closure_kind()
|
||||
&& !found_kind.extends(expected_kind)
|
||||
{
|
||||
if let Some((_, Some(parent))) = obligation.cause.code().parent() {
|
||||
if let Some((_, Some(parent))) = obligation.cause.code().parent_with_predicate() {
|
||||
// If we have a derived obligation, then the parent will be a `AsyncFn*` goal.
|
||||
trait_ref = parent.to_poly_trait_ref();
|
||||
} else if let &ObligationCauseCode::FunctionArg { arg_hir_id, .. } =
|
||||
|
@ -945,7 +945,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
let Some(typeck) = &self.typeck_results else {
|
||||
return false;
|
||||
};
|
||||
let Some((ObligationCauseCode::QuestionMark, Some(y))) = obligation.cause.code().parent()
|
||||
let Some((ObligationCauseCode::QuestionMark, Some(y))) =
|
||||
obligation.cause.code().parent_with_predicate()
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
|
@ -1198,7 +1199,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
|
||||
let mut code = obligation.cause.code();
|
||||
let mut pred = obligation.predicate.as_trait_clause();
|
||||
while let Some((next_code, next_pred)) = code.parent() {
|
||||
while let Some((next_code, next_pred)) = code.parent_with_predicate() {
|
||||
if let Some(pred) = pred {
|
||||
self.enter_forall(pred, |pred| {
|
||||
diag.note(format!(
|
||||
|
@ -2114,7 +2115,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
let mut code = obligation.cause.code();
|
||||
let mut trait_pred = trait_predicate;
|
||||
let mut peeled = false;
|
||||
while let Some((parent_code, parent_trait_pred)) = code.parent() {
|
||||
while let Some((parent_code, parent_trait_pred)) = code.parent_with_predicate() {
|
||||
code = parent_code;
|
||||
if let Some(parent_trait_pred) = parent_trait_pred {
|
||||
trait_pred = parent_trait_pred;
|
||||
|
|
|
@ -464,7 +464,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
|
||||
// Get the root obligation, since the leaf obligation we have may be unhelpful (#87437)
|
||||
let mut real_trait_pred = trait_pred;
|
||||
while let Some((parent_code, parent_trait_pred)) = code.parent() {
|
||||
while let Some((parent_code, parent_trait_pred)) = code.parent_with_predicate() {
|
||||
code = parent_code;
|
||||
if let Some(parent_trait_pred) = parent_trait_pred {
|
||||
real_trait_pred = parent_trait_pred;
|
||||
|
@ -1447,7 +1447,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
let mut span = obligation.cause.span;
|
||||
let mut trait_pred = trait_pred;
|
||||
let mut code = obligation.cause.code();
|
||||
while let Some((c, Some(parent_trait_pred))) = code.parent() {
|
||||
while let Some((c, Some(parent_trait_pred))) = code.parent_with_predicate() {
|
||||
// We want the root obligation, in order to detect properly handle
|
||||
// `for _ in &mut &mut vec![] {}`.
|
||||
code = c;
|
||||
|
@ -3470,6 +3470,59 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
)
|
||||
});
|
||||
}
|
||||
ObligationCauseCode::ImplDerivedHost(ref data) => {
|
||||
let self_ty =
|
||||
self.resolve_vars_if_possible(data.derived.parent_host_pred.self_ty());
|
||||
let msg = format!(
|
||||
"required for `{self_ty}` to implement `{} {}`",
|
||||
data.derived.parent_host_pred.skip_binder().constness,
|
||||
data.derived
|
||||
.parent_host_pred
|
||||
.map_bound(|pred| pred.trait_ref)
|
||||
.print_only_trait_path(),
|
||||
);
|
||||
match tcx.hir().get_if_local(data.impl_def_id) {
|
||||
Some(Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
|
||||
..
|
||||
})) => {
|
||||
let mut spans = vec![self_ty.span];
|
||||
spans.extend(of_trait.as_ref().map(|t| t.path.span));
|
||||
let mut spans: MultiSpan = spans.into();
|
||||
spans.push_span_label(data.span, "unsatisfied trait bound introduced here");
|
||||
err.span_note(spans, msg);
|
||||
}
|
||||
_ => {
|
||||
err.note(msg);
|
||||
}
|
||||
}
|
||||
ensure_sufficient_stack(|| {
|
||||
self.note_obligation_cause_code(
|
||||
body_id,
|
||||
err,
|
||||
data.derived.parent_host_pred,
|
||||
param_env,
|
||||
&data.derived.parent_code,
|
||||
obligated_types,
|
||||
seen_requirements,
|
||||
long_ty_file,
|
||||
)
|
||||
});
|
||||
}
|
||||
ObligationCauseCode::BuiltinDerivedHost(ref data) => {
|
||||
ensure_sufficient_stack(|| {
|
||||
self.note_obligation_cause_code(
|
||||
body_id,
|
||||
err,
|
||||
data.parent_host_pred,
|
||||
param_env,
|
||||
&data.parent_code,
|
||||
obligated_types,
|
||||
seen_requirements,
|
||||
long_ty_file,
|
||||
)
|
||||
});
|
||||
}
|
||||
ObligationCauseCode::WellFormedDerived(ref data) => {
|
||||
let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred);
|
||||
let parent_predicate = parent_trait_ref;
|
||||
|
|
|
@ -430,6 +430,7 @@ impl<'tcx> BestObligation<'tcx> {
|
|||
matches!(
|
||||
nested_goal.source(),
|
||||
GoalSource::ImplWhereBound
|
||||
| GoalSource::AliasBoundConstCondition
|
||||
| GoalSource::InstantiateHigherRanked
|
||||
| GoalSource::AliasWellFormed
|
||||
) && match self.consider_ambiguities {
|
||||
|
@ -491,8 +492,11 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
|
|||
// for normalizes-to.
|
||||
let pred_kind = goal.goal().predicate.kind();
|
||||
let child_mode = match pred_kind.skip_binder() {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(parent_trait_pred)) => {
|
||||
ChildMode::Trait(pred_kind.rebind(parent_trait_pred))
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
|
||||
ChildMode::Trait(pred_kind.rebind(pred))
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(pred)) => {
|
||||
ChildMode::Host(pred_kind.rebind(pred))
|
||||
}
|
||||
ty::PredicateKind::NormalizesTo(normalizes_to)
|
||||
if matches!(
|
||||
|
@ -521,7 +525,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
|
|||
|
||||
let obligation;
|
||||
match (child_mode, nested_goal.source()) {
|
||||
(ChildMode::Trait(_), GoalSource::Misc) => {
|
||||
(ChildMode::Trait(_) | ChildMode::Host(_), GoalSource::Misc) => {
|
||||
continue;
|
||||
}
|
||||
(ChildMode::Trait(parent_trait_pred), GoalSource::ImplWhereBound) => {
|
||||
|
@ -534,11 +538,25 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
|
|||
));
|
||||
impl_where_bound_count += 1;
|
||||
}
|
||||
(
|
||||
ChildMode::Host(parent_host_pred),
|
||||
GoalSource::ImplWhereBound | GoalSource::AliasBoundConstCondition,
|
||||
) => {
|
||||
obligation = make_obligation(derive_host_cause(
|
||||
tcx,
|
||||
candidate.kind(),
|
||||
self.obligation.cause.clone(),
|
||||
impl_where_bound_count,
|
||||
parent_host_pred,
|
||||
));
|
||||
impl_where_bound_count += 1;
|
||||
}
|
||||
// Skip over a higher-ranked predicate.
|
||||
(_, GoalSource::InstantiateHigherRanked) => {
|
||||
obligation = self.obligation.clone();
|
||||
}
|
||||
(ChildMode::PassThrough, _) | (_, GoalSource::AliasWellFormed) => {
|
||||
(ChildMode::PassThrough, _)
|
||||
| (_, GoalSource::AliasWellFormed | GoalSource::AliasBoundConstCondition) => {
|
||||
obligation = make_obligation(self.obligation.cause.clone());
|
||||
}
|
||||
}
|
||||
|
@ -592,6 +610,10 @@ enum ChildMode<'tcx> {
|
|||
// and skip all `GoalSource::Misc`, which represent useless obligations
|
||||
// such as alias-eq which may not hold.
|
||||
Trait(ty::PolyTraitPredicate<'tcx>),
|
||||
// Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`,
|
||||
// and skip all `GoalSource::Misc`, which represent useless obligations
|
||||
// such as alias-eq which may not hold.
|
||||
Host(ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>),
|
||||
// Skip trying to derive an `ObligationCause` from this obligation, and
|
||||
// report *all* sub-obligations as if they came directly from the parent
|
||||
// obligation.
|
||||
|
@ -633,3 +655,52 @@ fn derive_cause<'tcx>(
|
|||
};
|
||||
cause
|
||||
}
|
||||
|
||||
fn derive_host_cause<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
candidate_kind: inspect::ProbeKind<TyCtxt<'tcx>>,
|
||||
mut cause: ObligationCause<'tcx>,
|
||||
idx: usize,
|
||||
parent_host_pred: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
|
||||
) -> ObligationCause<'tcx> {
|
||||
match candidate_kind {
|
||||
inspect::ProbeKind::TraitCandidate {
|
||||
source: CandidateSource::Impl(impl_def_id),
|
||||
result: _,
|
||||
} => {
|
||||
if let Some((_, span)) = tcx
|
||||
.predicates_of(impl_def_id)
|
||||
.instantiate_identity(tcx)
|
||||
.into_iter()
|
||||
.chain(tcx.const_conditions(impl_def_id).instantiate_identity(tcx).into_iter().map(
|
||||
|(trait_ref, span)| {
|
||||
(
|
||||
trait_ref.to_host_effect_clause(
|
||||
tcx,
|
||||
parent_host_pred.skip_binder().constness,
|
||||
),
|
||||
span,
|
||||
)
|
||||
},
|
||||
))
|
||||
.nth(idx)
|
||||
{
|
||||
cause =
|
||||
cause.derived_host_cause(parent_host_pred, |derived| {
|
||||
ObligationCauseCode::ImplDerivedHost(Box::new(
|
||||
traits::ImplDerivedHostCause { derived, impl_def_id, span },
|
||||
))
|
||||
})
|
||||
}
|
||||
}
|
||||
inspect::ProbeKind::TraitCandidate {
|
||||
source: CandidateSource::BuiltinImpl(..),
|
||||
result: _,
|
||||
} => {
|
||||
cause =
|
||||
cause.derived_host_cause(parent_host_pred, ObligationCauseCode::BuiltinDerivedHost);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
cause
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use rustc_hir as hir;
|
||||
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes};
|
||||
use rustc_infer::traits::{ImplSource, Obligation, PredicateObligation};
|
||||
use rustc_infer::traits::{
|
||||
ImplDerivedHostCause, ImplSource, Obligation, ObligationCauseCode, PredicateObligation,
|
||||
};
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
|
||||
use rustc_middle::ty::{self, TypingMode};
|
||||
|
@ -248,9 +250,22 @@ fn evaluate_host_effect_from_selection_candiate<'tcx>(
|
|||
tcx.const_conditions(impl_.impl_def_id)
|
||||
.instantiate(tcx, impl_.args)
|
||||
.into_iter()
|
||||
.map(|(trait_ref, _)| {
|
||||
obligation.with(
|
||||
.map(|(trait_ref, span)| {
|
||||
Obligation::new(
|
||||
tcx,
|
||||
obligation.cause.clone().derived_host_cause(
|
||||
ty::Binder::dummy(obligation.predicate),
|
||||
|derived| {
|
||||
ObligationCauseCode::ImplDerivedHost(Box::new(
|
||||
ImplDerivedHostCause {
|
||||
derived,
|
||||
impl_def_id: impl_.impl_def_id,
|
||||
span,
|
||||
},
|
||||
))
|
||||
},
|
||||
),
|
||||
obligation.param_env,
|
||||
trait_ref
|
||||
.to_host_effect_clause(tcx, obligation.predicate.constness),
|
||||
)
|
||||
|
|
|
@ -89,6 +89,7 @@ impl_binder_encode_decode! {
|
|||
ty::ExistentialPredicate<I>,
|
||||
ty::TraitRef<I>,
|
||||
ty::ExistentialTraitRef<I>,
|
||||
ty::HostEffectPredicate<I>,
|
||||
}
|
||||
|
||||
impl<I: Interner, T> Binder<I, T>
|
||||
|
|
|
@ -68,6 +68,10 @@ pub enum GoalSource {
|
|||
/// FIXME(-Znext-solver=coinductive): Explain how and why this
|
||||
/// changes whether cycles are coinductive.
|
||||
ImplWhereBound,
|
||||
/// Const conditions that need to hold for `~const` alias bounds to hold.
|
||||
///
|
||||
/// FIXME(-Znext-solver=coinductive): Are these even coinductive?
|
||||
AliasBoundConstCondition,
|
||||
/// Instantiating a higher-ranked goal and re-proving it.
|
||||
InstantiateHigherRanked,
|
||||
/// Predicate required for an alias projection to be well-formed.
|
||||
|
|
|
@ -11,12 +11,30 @@ error[E0284]: type annotations needed: cannot normalize `<&T as ConstName>::{con
|
|||
|
|
||||
LL | impl<T: ?Sized + ConstName> const ConstName for &T
|
||||
| ^^ cannot normalize `<&T as ConstName>::{constant#0}`
|
||||
|
|
||||
note: required for `&T` to implement `~const ConstName`
|
||||
--> $DIR/issue-88119.rs:19:35
|
||||
|
|
||||
LL | impl<T: ?Sized + ConstName> const ConstName for &T
|
||||
| ^^^^^^^^^ ^^
|
||||
LL | where
|
||||
LL | [(); name_len::<T>()]:,
|
||||
| --------------------- unsatisfied trait bound introduced here
|
||||
|
||||
error[E0284]: type annotations needed: cannot normalize `<&mut T as ConstName>::{constant#0}`
|
||||
--> $DIR/issue-88119.rs:26:49
|
||||
|
|
||||
LL | impl<T: ?Sized + ConstName> const ConstName for &mut T
|
||||
| ^^^^^^ cannot normalize `<&mut T as ConstName>::{constant#0}`
|
||||
|
|
||||
note: required for `&mut T` to implement `~const ConstName`
|
||||
--> $DIR/issue-88119.rs:26:35
|
||||
|
|
||||
LL | impl<T: ?Sized + ConstName> const ConstName for &mut T
|
||||
| ^^^^^^^^^ ^^^^^^
|
||||
LL | where
|
||||
LL | [(); name_len::<T>()]:,
|
||||
| --------------------- unsatisfied trait bound introduced here
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ LL | T::Assoc::<U>::func();
|
|||
| ^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: the trait bound `U: ~const Other` is not satisfied
|
||||
--> $DIR/assoc-type-const-bound-usage-fail-2.rs:27:5
|
||||
--> $DIR/assoc-type-const-bound-usage-fail-2.rs:26:5
|
||||
|
|
||||
LL | <T as Trait>::Assoc::<U>::func();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
error[E0277]: the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
|
||||
error[E0277]: the trait bound `U: ~const Other` is not satisfied
|
||||
--> $DIR/assoc-type-const-bound-usage-fail-2.rs:24:5
|
||||
|
|
||||
LL | T::Assoc::<U>::func();
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
|
||||
--> $DIR/assoc-type-const-bound-usage-fail-2.rs:27:5
|
||||
error[E0277]: the trait bound `U: ~const Other` is not satisfied
|
||||
--> $DIR/assoc-type-const-bound-usage-fail-2.rs:26:5
|
||||
|
|
||||
LL | <T as Trait>::Assoc::<U>::func();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -22,11 +22,9 @@ trait Other {}
|
|||
|
||||
const fn fails<T: ~const Trait, U: Other>() {
|
||||
T::Assoc::<U>::func();
|
||||
//[current]~^ ERROR the trait bound `U: ~const Other` is not satisfied
|
||||
//[next]~^^ ERROR the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
|
||||
//~^ ERROR the trait bound `U: ~const Other` is not satisfied
|
||||
<T as Trait>::Assoc::<U>::func();
|
||||
//[current]~^ ERROR the trait bound `U: ~const Other` is not satisfied
|
||||
//[next]~^^ ERROR the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
|
||||
//~^ ERROR the trait bound `U: ~const Other` is not satisfied
|
||||
}
|
||||
|
||||
const fn works<T: ~const Trait, U: ~const Other>() {
|
||||
|
|
|
@ -16,6 +16,11 @@ error[E0277]: the trait bound `T: ~const Bar` is not satisfied
|
|||
LL | type Assoc<T> = C<T>
|
||||
| ^^^^
|
||||
|
|
||||
note: required for `C<T>` to implement `~const Bar`
|
||||
--> $DIR/item-bound-entailment-fails.rs:14:15
|
||||
|
|
||||
LL | impl<T> const Bar for C<T> where T: ~const Bar {}
|
||||
| ^^^ ^^^^ ------ unsatisfied trait bound introduced here
|
||||
note: required by a bound in `Foo::Assoc`
|
||||
--> $DIR/item-bound-entailment-fails.rs:5:20
|
||||
|
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue