Rollup merge of #134638 - compiler-errors:fx-item-bounds, r=lcnr
Fix effect predicates from item bounds in old solver r? lcnr
This commit is contained in:
commit
c2f44cd32c
13 changed files with 202 additions and 78 deletions
|
@ -1,13 +1,15 @@
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt};
|
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes};
|
||||||
use rustc_infer::traits::{ImplSource, Obligation, PredicateObligation};
|
use rustc_infer::traits::{ImplSource, Obligation, PredicateObligation};
|
||||||
use rustc_middle::span_bug;
|
use rustc_middle::span_bug;
|
||||||
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
|
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
|
||||||
use rustc_middle::ty::{self, TypingMode};
|
use rustc_middle::ty::{self, TypingMode};
|
||||||
|
use rustc_type_ir::elaborate::elaborate;
|
||||||
use rustc_type_ir::solve::NoSolution;
|
use rustc_type_ir::solve::NoSolution;
|
||||||
use thin_vec::ThinVec;
|
use thin_vec::{ThinVec, thin_vec};
|
||||||
|
|
||||||
use super::SelectionContext;
|
use super::SelectionContext;
|
||||||
|
use super::normalize::normalize_with_depth_to;
|
||||||
|
|
||||||
pub type HostEffectObligation<'tcx> = Obligation<'tcx, ty::HostEffectPredicate<'tcx>>;
|
pub type HostEffectObligation<'tcx> = Obligation<'tcx, ty::HostEffectPredicate<'tcx>>;
|
||||||
|
|
||||||
|
@ -38,6 +40,12 @@ pub fn evaluate_host_effect_obligation<'tcx>(
|
||||||
Err(EvaluationFailure::NoSolution) => {}
|
Err(EvaluationFailure::NoSolution) => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match evaluate_host_effect_from_item_bounds(selcx, obligation) {
|
||||||
|
Ok(result) => return Ok(result),
|
||||||
|
Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
|
||||||
|
Err(EvaluationFailure::NoSolution) => {}
|
||||||
|
}
|
||||||
|
|
||||||
match evaluate_host_effect_from_selection_candiate(selcx, obligation) {
|
match evaluate_host_effect_from_selection_candiate(selcx, obligation) {
|
||||||
Ok(result) => return Ok(result),
|
Ok(result) => return Ok(result),
|
||||||
Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
|
Err(EvaluationFailure::Ambiguous) => return Err(EvaluationFailure::Ambiguous),
|
||||||
|
@ -48,24 +56,45 @@ pub fn evaluate_host_effect_obligation<'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_candidate<'tcx>(
|
fn match_candidate<'tcx>(
|
||||||
infcx: &InferCtxt<'tcx>,
|
selcx: &mut SelectionContext<'_, 'tcx>,
|
||||||
obligation: &HostEffectObligation<'tcx>,
|
obligation: &HostEffectObligation<'tcx>,
|
||||||
candidate: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
|
candidate: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
|
||||||
|
candidate_is_unnormalized: bool,
|
||||||
|
more_nested: impl FnOnce(&mut SelectionContext<'_, 'tcx>, &mut ThinVec<PredicateObligation<'tcx>>),
|
||||||
) -> Result<ThinVec<PredicateObligation<'tcx>>, NoSolution> {
|
) -> Result<ThinVec<PredicateObligation<'tcx>>, NoSolution> {
|
||||||
if !candidate.skip_binder().constness.satisfies(obligation.predicate.constness) {
|
if !candidate.skip_binder().constness.satisfies(obligation.predicate.constness) {
|
||||||
return Err(NoSolution);
|
return Err(NoSolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
let candidate = infcx.instantiate_binder_with_fresh_vars(
|
let mut candidate = selcx.infcx.instantiate_binder_with_fresh_vars(
|
||||||
obligation.cause.span,
|
obligation.cause.span,
|
||||||
BoundRegionConversionTime::HigherRankedType,
|
BoundRegionConversionTime::HigherRankedType,
|
||||||
candidate,
|
candidate,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut nested = infcx
|
let mut nested = thin_vec![];
|
||||||
.at(&obligation.cause, obligation.param_env)
|
|
||||||
.eq(DefineOpaqueTypes::Yes, obligation.predicate.trait_ref, candidate.trait_ref)?
|
// Unlike param-env bounds, item bounds may not be normalized.
|
||||||
.into_obligations();
|
if candidate_is_unnormalized {
|
||||||
|
candidate = normalize_with_depth_to(
|
||||||
|
selcx,
|
||||||
|
obligation.param_env,
|
||||||
|
obligation.cause.clone(),
|
||||||
|
obligation.recursion_depth,
|
||||||
|
candidate,
|
||||||
|
&mut nested,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
nested.extend(
|
||||||
|
selcx
|
||||||
|
.infcx
|
||||||
|
.at(&obligation.cause, obligation.param_env)
|
||||||
|
.eq(DefineOpaqueTypes::Yes, obligation.predicate.trait_ref, candidate.trait_ref)?
|
||||||
|
.into_obligations(),
|
||||||
|
);
|
||||||
|
|
||||||
|
more_nested(selcx, &mut nested);
|
||||||
|
|
||||||
for nested in &mut nested {
|
for nested in &mut nested {
|
||||||
nested.set_depth_from_parent(obligation.recursion_depth);
|
nested.set_depth_from_parent(obligation.recursion_depth);
|
||||||
|
@ -82,41 +111,121 @@ fn evaluate_host_effect_from_bounds<'tcx>(
|
||||||
let drcx = DeepRejectCtxt::relate_rigid_rigid(selcx.tcx());
|
let drcx = DeepRejectCtxt::relate_rigid_rigid(selcx.tcx());
|
||||||
let mut candidate = None;
|
let mut candidate = None;
|
||||||
|
|
||||||
for predicate in obligation.param_env.caller_bounds() {
|
for clause in obligation.param_env.caller_bounds() {
|
||||||
let bound_predicate = predicate.kind();
|
let bound_clause = clause.kind();
|
||||||
if let ty::ClauseKind::HostEffect(data) = predicate.kind().skip_binder() {
|
let ty::ClauseKind::HostEffect(data) = bound_clause.skip_binder() else {
|
||||||
let data = bound_predicate.rebind(data);
|
continue;
|
||||||
if data.skip_binder().trait_ref.def_id != obligation.predicate.trait_ref.def_id {
|
};
|
||||||
continue;
|
let data = bound_clause.rebind(data);
|
||||||
}
|
if data.skip_binder().trait_ref.def_id != obligation.predicate.trait_ref.def_id {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if !drcx.args_may_unify(
|
if !drcx
|
||||||
obligation.predicate.trait_ref.args,
|
.args_may_unify(obligation.predicate.trait_ref.args, data.skip_binder().trait_ref.args)
|
||||||
data.skip_binder().trait_ref.args,
|
{
|
||||||
) {
|
continue;
|
||||||
continue;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let is_match = infcx.probe(|_| match_candidate(infcx, obligation, data).is_ok());
|
let is_match =
|
||||||
|
infcx.probe(|_| match_candidate(selcx, obligation, data, false, |_, _| {}).is_ok());
|
||||||
|
|
||||||
if is_match {
|
if is_match {
|
||||||
if candidate.is_some() {
|
if candidate.is_some() {
|
||||||
return Err(EvaluationFailure::Ambiguous);
|
return Err(EvaluationFailure::Ambiguous);
|
||||||
} else {
|
} else {
|
||||||
candidate = Some(data);
|
candidate = Some(data);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(data) = candidate {
|
if let Some(data) = candidate {
|
||||||
Ok(match_candidate(infcx, obligation, data)
|
Ok(match_candidate(selcx, obligation, data, false, |_, _| {})
|
||||||
.expect("candidate matched before, so it should match again"))
|
.expect("candidate matched before, so it should match again"))
|
||||||
} else {
|
} else {
|
||||||
Err(EvaluationFailure::NoSolution)
|
Err(EvaluationFailure::NoSolution)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn evaluate_host_effect_from_item_bounds<'tcx>(
|
||||||
|
selcx: &mut SelectionContext<'_, 'tcx>,
|
||||||
|
obligation: &HostEffectObligation<'tcx>,
|
||||||
|
) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
|
||||||
|
let infcx = selcx.infcx;
|
||||||
|
let tcx = infcx.tcx;
|
||||||
|
let drcx = DeepRejectCtxt::relate_rigid_rigid(selcx.tcx());
|
||||||
|
let mut candidate = None;
|
||||||
|
|
||||||
|
let mut consider_ty = obligation.predicate.self_ty();
|
||||||
|
while let ty::Alias(kind @ (ty::Projection | ty::Opaque), alias_ty) = *consider_ty.kind() {
|
||||||
|
if tcx.is_conditionally_const(alias_ty.def_id) {
|
||||||
|
for clause in elaborate(
|
||||||
|
tcx,
|
||||||
|
tcx.explicit_implied_const_bounds(alias_ty.def_id)
|
||||||
|
.iter_instantiated_copied(tcx, alias_ty.args)
|
||||||
|
.map(|(trait_ref, _)| {
|
||||||
|
trait_ref.to_host_effect_clause(tcx, obligation.predicate.constness)
|
||||||
|
}),
|
||||||
|
) {
|
||||||
|
let bound_clause = clause.kind();
|
||||||
|
let ty::ClauseKind::HostEffect(data) = bound_clause.skip_binder() else {
|
||||||
|
unreachable!("should not elaborate non-HostEffect from HostEffect")
|
||||||
|
};
|
||||||
|
let data = bound_clause.rebind(data);
|
||||||
|
if data.skip_binder().trait_ref.def_id != obligation.predicate.trait_ref.def_id {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !drcx.args_may_unify(
|
||||||
|
obligation.predicate.trait_ref.args,
|
||||||
|
data.skip_binder().trait_ref.args,
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let is_match = infcx
|
||||||
|
.probe(|_| match_candidate(selcx, obligation, data, true, |_, _| {}).is_ok());
|
||||||
|
|
||||||
|
if is_match {
|
||||||
|
if candidate.is_some() {
|
||||||
|
return Err(EvaluationFailure::Ambiguous);
|
||||||
|
} else {
|
||||||
|
candidate = Some((data, alias_ty));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if kind != ty::Projection {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
consider_ty = alias_ty.self_ty();
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some((data, alias_ty)) = candidate {
|
||||||
|
Ok(match_candidate(selcx, obligation, data, true, |selcx, nested| {
|
||||||
|
// An alias bound only holds if we also check the const conditions
|
||||||
|
// of the alias, so we need to register those, too.
|
||||||
|
let const_conditions = normalize_with_depth_to(
|
||||||
|
selcx,
|
||||||
|
obligation.param_env,
|
||||||
|
obligation.cause.clone(),
|
||||||
|
obligation.recursion_depth,
|
||||||
|
tcx.const_conditions(alias_ty.def_id).instantiate(tcx, alias_ty.args),
|
||||||
|
nested,
|
||||||
|
);
|
||||||
|
nested.extend(const_conditions.into_iter().map(|(trait_ref, _)| {
|
||||||
|
obligation
|
||||||
|
.with(tcx, trait_ref.to_host_effect_clause(tcx, obligation.predicate.constness))
|
||||||
|
}));
|
||||||
|
})
|
||||||
|
.expect("candidate matched before, so it should match again"))
|
||||||
|
} else {
|
||||||
|
Err(EvaluationFailure::NoSolution)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn evaluate_host_effect_from_selection_candiate<'tcx>(
|
fn evaluate_host_effect_from_selection_candiate<'tcx>(
|
||||||
selcx: &mut SelectionContext<'_, 'tcx>,
|
selcx: &mut SelectionContext<'_, 'tcx>,
|
||||||
obligation: &HostEffectObligation<'tcx>,
|
obligation: &HostEffectObligation<'tcx>,
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
//@ compile-flags: -Znext-solver
|
//@ revisions: current next
|
||||||
|
//@[next] compile-flags: -Znext-solver
|
||||||
//@ check-pass
|
//@ check-pass
|
||||||
|
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
//@ compile-flags: -Znext-solver
|
//@ check-pass
|
||||||
//@ known-bug: unknown
|
|
||||||
|
|
||||||
#![feature(const_trait_impl, generic_const_exprs)]
|
#![feature(const_trait_impl, generic_const_exprs)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
error: `-Znext-solver=globally` and `generic_const_exprs` are incompatible, using them at the same time is not allowed
|
|
||||||
--> $DIR/assoc-type-const-bound-usage-1.rs:4:30
|
|
||||||
|
|
|
||||||
LL | #![feature(const_trait_impl, generic_const_exprs)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= help: remove one of these features
|
|
||||||
|
|
||||||
error[E0284]: type annotations needed: cannot normalize `unqualified<T>::{constant#0}`
|
|
||||||
--> $DIR/assoc-type-const-bound-usage-1.rs:15:37
|
|
||||||
|
|
|
||||||
LL | fn unqualified<T: const Trait>() -> Type<{ T::Assoc::func() }> {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `unqualified<T>::{constant#0}`
|
|
||||||
|
|
||||||
error[E0284]: type annotations needed: cannot normalize `qualified<T>::{constant#0}`
|
|
||||||
--> $DIR/assoc-type-const-bound-usage-1.rs:19:35
|
|
||||||
|
|
|
||||||
LL | fn qualified<T: const Trait>() -> Type<{ <T as Trait>::Assoc::func() }> {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `qualified<T>::{constant#0}`
|
|
||||||
|
|
||||||
error[E0284]: type annotations needed: cannot normalize `unqualified<T>::{constant#0}`
|
|
||||||
--> $DIR/assoc-type-const-bound-usage-1.rs:16:5
|
|
||||||
|
|
|
||||||
LL | Type
|
|
||||||
| ^^^^ cannot normalize `unqualified<T>::{constant#0}`
|
|
||||||
|
|
||||||
error[E0284]: type annotations needed: cannot normalize `qualified<T>::{constant#0}`
|
|
||||||
--> $DIR/assoc-type-const-bound-usage-1.rs:20:5
|
|
||||||
|
|
|
||||||
LL | Type
|
|
||||||
| ^^^^ cannot normalize `qualified<T>::{constant#0}`
|
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0284`.
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
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 `U: ~const Other` is not satisfied
|
||||||
|
--> $DIR/assoc-type-const-bound-usage-fail-2.rs:27:5
|
||||||
|
|
|
||||||
|
LL | <T as Trait>::Assoc::<U>::func();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
|
@ -1,11 +1,11 @@
|
||||||
error[E0277]: the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
|
error[E0277]: the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
|
||||||
--> $DIR/assoc-type-const-bound-usage-fail-2.rs:23:5
|
--> $DIR/assoc-type-const-bound-usage-fail-2.rs:24:5
|
||||||
|
|
|
|
||||||
LL | T::Assoc::<U>::func();
|
LL | T::Assoc::<U>::func();
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0277]: the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
|
error[E0277]: the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
|
||||||
--> $DIR/assoc-type-const-bound-usage-fail-2.rs:25:5
|
--> $DIR/assoc-type-const-bound-usage-fail-2.rs:27:5
|
||||||
|
|
|
|
||||||
LL | <T as Trait>::Assoc::<U>::func();
|
LL | <T as Trait>::Assoc::<U>::func();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
|
@ -1,4 +1,5 @@
|
||||||
//@ compile-flags: -Znext-solver
|
//@ revisions: current next
|
||||||
|
//@[next] compile-flags: -Znext-solver
|
||||||
|
|
||||||
// Check that `~const` item bounds only hold if the where clauses on the
|
// Check that `~const` item bounds only hold if the where clauses on the
|
||||||
// associated type are also const.
|
// associated type are also const.
|
||||||
|
@ -21,9 +22,11 @@ trait Other {}
|
||||||
|
|
||||||
const fn fails<T: ~const Trait, U: Other>() {
|
const fn fails<T: ~const Trait, U: Other>() {
|
||||||
T::Assoc::<U>::func();
|
T::Assoc::<U>::func();
|
||||||
//~^ ERROR the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
|
//[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
|
||||||
<T as Trait>::Assoc::<U>::func();
|
<T as Trait>::Assoc::<U>::func();
|
||||||
//~^ ERROR the trait bound `<T as Trait>::Assoc<U>: ~const Trait` is not satisfied
|
//[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
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn works<T: ~const Trait, U: ~const Other>() {
|
const fn works<T: ~const Trait, U: ~const Other>() {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
error[E0277]: the trait bound `T: ~const Trait` is not satisfied
|
error[E0277]: the trait bound `T: ~const Trait` is not satisfied
|
||||||
--> $DIR/assoc-type-const-bound-usage-fail.rs:16:5
|
--> $DIR/assoc-type-const-bound-usage-fail.rs:17:5
|
||||||
|
|
|
|
||||||
LL | T::Assoc::func();
|
LL | T::Assoc::func();
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
||||||
error[E0277]: the trait bound `T: ~const Trait` is not satisfied
|
error[E0277]: the trait bound `T: ~const Trait` is not satisfied
|
||||||
--> $DIR/assoc-type-const-bound-usage-fail.rs:18:5
|
--> $DIR/assoc-type-const-bound-usage-fail.rs:19:5
|
||||||
|
|
|
|
||||||
LL | <T as Trait>::Assoc::func();
|
LL | <T as Trait>::Assoc::func();
|
||||||
| ^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^
|
|
@ -0,0 +1,15 @@
|
||||||
|
error[E0277]: the trait bound `T: ~const Trait` is not satisfied
|
||||||
|
--> $DIR/assoc-type-const-bound-usage-fail.rs:17:5
|
||||||
|
|
|
||||||
|
LL | T::Assoc::func();
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `T: ~const Trait` is not satisfied
|
||||||
|
--> $DIR/assoc-type-const-bound-usage-fail.rs:19:5
|
||||||
|
|
|
||||||
|
LL | <T as Trait>::Assoc::func();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
|
@ -1,4 +1,5 @@
|
||||||
//@ compile-flags: -Znext-solver
|
//@ revisions: current next
|
||||||
|
//@[next] compile-flags: -Znext-solver
|
||||||
|
|
||||||
// Check that `~const` item bounds only hold if the parent trait is `~const`.
|
// Check that `~const` item bounds only hold if the parent trait is `~const`.
|
||||||
// i.e. check that we validate the const conditions for the associated type
|
// i.e. check that we validate the const conditions for the associated type
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
error[E0277]: the trait bound `NonConstAdd: ~const Add` is not satisfied
|
error[E0277]: the trait bound `NonConstAdd: ~const Add` is not satisfied
|
||||||
--> $DIR/assoc-type.rs:36:16
|
--> $DIR/assoc-type.rs:37:16
|
||||||
|
|
|
|
||||||
LL | type Bar = NonConstAdd;
|
LL | type Bar = NonConstAdd;
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: required by a bound in `Foo::Bar`
|
note: required by a bound in `Foo::Bar`
|
||||||
--> $DIR/assoc-type.rs:32:15
|
--> $DIR/assoc-type.rs:33:15
|
||||||
|
|
|
|
||||||
LL | type Bar: ~const Add;
|
LL | type Bar: ~const Add;
|
||||||
| ^^^^^^ required by this bound in `Foo::Bar`
|
| ^^^^^^ required by this bound in `Foo::Bar`
|
15
tests/ui/traits/const-traits/assoc-type.next.stderr
Normal file
15
tests/ui/traits/const-traits/assoc-type.next.stderr
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
error[E0277]: the trait bound `NonConstAdd: ~const Add` is not satisfied
|
||||||
|
--> $DIR/assoc-type.rs:37:16
|
||||||
|
|
|
||||||
|
LL | type Bar = NonConstAdd;
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: required by a bound in `Foo::Bar`
|
||||||
|
--> $DIR/assoc-type.rs:33:15
|
||||||
|
|
|
||||||
|
LL | type Bar: ~const Add;
|
||||||
|
| ^^^^^^ required by this bound in `Foo::Bar`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
|
@ -1,4 +1,5 @@
|
||||||
//@ compile-flags: -Znext-solver
|
//@ revisions: current next
|
||||||
|
//@[next] compile-flags: -Znext-solver
|
||||||
|
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl)]
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue