mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
address review comments
This commit is contained in:
parent
8b2fac9612
commit
65a0bee0b7
@ -397,8 +397,8 @@ language_item_table! {
|
||||
EffectsRuntime, sym::EffectsRuntime, effects_runtime, Target::Struct, GenericRequirement::None;
|
||||
EffectsNoRuntime, sym::EffectsNoRuntime, effects_no_runtime, Target::Struct, GenericRequirement::None;
|
||||
EffectsMaybe, sym::EffectsMaybe, effects_maybe, Target::Struct, GenericRequirement::None;
|
||||
EffectsMin, sym::EffectsMin, effects_min, Target::Trait, GenericRequirement::None;
|
||||
EffectsMinOutput, sym::EffectsMinOutput, effects_min_output, Target::AssocTy, GenericRequirement::None;
|
||||
EffectsIntersection, sym::EffectsIntersection, effects_intersection, Target::Trait, GenericRequirement::None;
|
||||
EffectsIntersectionOutput, sym::EffectsIntersectionOutput, effects_intersection_output, Target::AssocTy, GenericRequirement::None;
|
||||
EffectsCompat, sym::EffectsCompat, effects_compat, Target::Trait, GenericRequirement::Exact(1);
|
||||
EffectsTyCompat, sym::EffectsTyCompat, effects_ty_compat, Target::Trait, GenericRequirement::Exact(1);
|
||||
}
|
||||
|
@ -71,16 +71,19 @@ impl<'tcx> Bounds<'tcx> {
|
||||
}
|
||||
// For `T: ~const Tr` or `T: const Tr`, we need to add an additional bound on the
|
||||
// associated type of `<T as Tr>` and make sure that the effect is compatible.
|
||||
if let Some(compat_val) = match (tcx.def_kind(defining_def_id), constness) {
|
||||
let compat_val = match (tcx.def_kind(defining_def_id), constness) {
|
||||
// FIXME(effects): revisit the correctness of this
|
||||
(_, ty::BoundConstness::Const) => Some(tcx.consts.false_),
|
||||
(_, ty::BoundConstness::Const) => tcx.consts.false_,
|
||||
// body owners that can have trait bounds
|
||||
(DefKind::Const | DefKind::Fn | DefKind::AssocFn, ty::BoundConstness::ConstIfConst) => {
|
||||
Some(tcx.expected_host_effect_param_for_body(defining_def_id))
|
||||
tcx.expected_host_effect_param_for_body(defining_def_id)
|
||||
}
|
||||
|
||||
(_, ty::BoundConstness::NotConst) => {
|
||||
tcx.has_attr(bound_trait_ref.def_id(), sym::const_trait).then_some(tcx.consts.true_)
|
||||
if !tcx.has_attr(bound_trait_ref.def_id(), sym::const_trait) {
|
||||
return;
|
||||
}
|
||||
tcx.consts.true_
|
||||
}
|
||||
|
||||
(
|
||||
@ -97,8 +100,12 @@ impl<'tcx> Bounds<'tcx> {
|
||||
let ty = bound_trait_ref
|
||||
.map_bound(|trait_ref| Ty::new_projection(tcx, assoc, trait_ref.args));
|
||||
|
||||
// Replace the binder with dummy types/lifetimes. This should work for any
|
||||
// binder as long as they don't have any bounds e.g. `for<T: Trait>`.
|
||||
// When the user has written `for<'a, T> X<'a, T>: ~const Foo`, replace the
|
||||
// binders to dummy ones i.e. `X<'static, ()>` so they can be referenced in
|
||||
// the `Min` associated type properly (which doesn't allow using `for<>`)
|
||||
// This should work for any bound variables as long as they don't have any
|
||||
// bounds e.g. `for<T: Trait>`.
|
||||
// FIXME(effects) reconsider this approach to allow compatibility with `for<T: Tr>`
|
||||
let ty = tcx.replace_bound_vars_uncached(
|
||||
ty,
|
||||
FnMutDelegate {
|
||||
@ -128,24 +135,23 @@ impl<'tcx> Bounds<'tcx> {
|
||||
tcx.dcx().span_delayed_bug(span, "invalid `~const` encountered");
|
||||
return;
|
||||
}
|
||||
} {
|
||||
// create a new projection type `<T as Tr>::Effects`
|
||||
let Some(assoc) = tcx.associated_type_for_effects(bound_trait_ref.def_id()) else {
|
||||
tcx.dcx().span_delayed_bug(
|
||||
span,
|
||||
"`~const` trait bound has no effect assoc yet no errors encountered?",
|
||||
);
|
||||
return;
|
||||
};
|
||||
let self_ty = Ty::new_projection(tcx, assoc, bound_trait_ref.skip_binder().args);
|
||||
// make `<T as Tr>::Effects: Compat<runtime>`
|
||||
let new_trait_ref = ty::TraitRef::new(
|
||||
tcx,
|
||||
tcx.require_lang_item(LangItem::EffectsCompat, Some(span)),
|
||||
[ty::GenericArg::from(self_ty), compat_val.into()],
|
||||
};
|
||||
// create a new projection type `<T as Tr>::Effects`
|
||||
let Some(assoc) = tcx.associated_type_for_effects(bound_trait_ref.def_id()) else {
|
||||
tcx.dcx().span_delayed_bug(
|
||||
span,
|
||||
"`~const` trait bound has no effect assoc yet no errors encountered?",
|
||||
);
|
||||
self.clauses.push((bound_trait_ref.rebind(new_trait_ref).upcast(tcx), span));
|
||||
}
|
||||
return;
|
||||
};
|
||||
let self_ty = Ty::new_projection(tcx, assoc, bound_trait_ref.skip_binder().args);
|
||||
// make `<T as Tr>::Effects: Compat<runtime>`
|
||||
let new_trait_ref = ty::TraitRef::new(
|
||||
tcx,
|
||||
tcx.require_lang_item(LangItem::EffectsCompat, Some(span)),
|
||||
[ty::GenericArg::from(self_ty), compat_val.into()],
|
||||
);
|
||||
self.clauses.push((bound_trait_ref.rebind(new_trait_ref).upcast(tcx), span));
|
||||
}
|
||||
|
||||
pub fn push_projection_bound(
|
||||
|
@ -137,7 +137,7 @@ pub(super) fn explicit_item_bounds_with_filter(
|
||||
let tup = Ty::new(tcx, ty::Tuple(preds.effects_min_tys));
|
||||
// FIXME(effects) span
|
||||
let span = tcx.def_span(def_id);
|
||||
let assoc = tcx.require_lang_item(hir::LangItem::EffectsMinOutput, Some(span));
|
||||
let assoc = tcx.require_lang_item(hir::LangItem::EffectsIntersectionOutput, Some(span));
|
||||
let proj = Ty::new_projection(tcx, assoc, [tup]);
|
||||
let self_proj = Ty::new_projection(
|
||||
tcx,
|
||||
|
@ -599,8 +599,8 @@ fn trait_lang_item_to_lang_item(lang_item: TraitSolverLangItem) -> LangItem {
|
||||
TraitSolverLangItem::DiscriminantKind => LangItem::DiscriminantKind,
|
||||
TraitSolverLangItem::DynMetadata => LangItem::DynMetadata,
|
||||
TraitSolverLangItem::EffectsMaybe => LangItem::EffectsMaybe,
|
||||
TraitSolverLangItem::EffectsMin => LangItem::EffectsMin,
|
||||
TraitSolverLangItem::EffectsMinOutput => LangItem::EffectsMinOutput,
|
||||
TraitSolverLangItem::EffectsIntersection => LangItem::EffectsIntersection,
|
||||
TraitSolverLangItem::EffectsIntersectionOutput => LangItem::EffectsIntersectionOutput,
|
||||
TraitSolverLangItem::EffectsNoRuntime => LangItem::EffectsNoRuntime,
|
||||
TraitSolverLangItem::EffectsRuntime => LangItem::EffectsRuntime,
|
||||
TraitSolverLangItem::FnPtrTrait => LangItem::FnPtrTrait,
|
||||
|
@ -270,7 +270,7 @@ where
|
||||
goal: Goal<I, Self>,
|
||||
) -> Vec<Candidate<I>>;
|
||||
|
||||
fn consider_builtin_effects_min_candidate(
|
||||
fn consider_builtin_effects_intersection_candidate(
|
||||
ecx: &mut EvalCtxt<'_, D>,
|
||||
goal: Goal<I, Self>,
|
||||
) -> Result<Candidate<I>, NoSolution>;
|
||||
@ -425,8 +425,8 @@ where
|
||||
G::consider_builtin_destruct_candidate(self, goal)
|
||||
} else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::TransmuteTrait) {
|
||||
G::consider_builtin_transmute_candidate(self, goal)
|
||||
} else if tcx.is_lang_item(trait_def_id, TraitSolverLangItem::EffectsMin) {
|
||||
G::consider_builtin_effects_min_candidate(self, goal)
|
||||
} else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::EffectsIntersection) {
|
||||
G::consider_builtin_effects_intersection_candidate(self, goal)
|
||||
} else {
|
||||
Err(NoSolution)
|
||||
};
|
||||
|
@ -865,7 +865,7 @@ where
|
||||
panic!("`BikeshedIntrinsicFrom` does not have an associated type: {:?}", goal)
|
||||
}
|
||||
|
||||
fn consider_builtin_effects_min_candidate(
|
||||
fn consider_builtin_effects_intersection_candidate(
|
||||
ecx: &mut EvalCtxt<'_, D>,
|
||||
goal: Goal<I, Self>,
|
||||
) -> Result<Candidate<I>, NoSolution> {
|
||||
@ -903,11 +903,15 @@ where
|
||||
let mut min = ty::EffectKind::Maybe;
|
||||
|
||||
for ty in types.iter() {
|
||||
// We can't find the intersection if the types used are generic.
|
||||
//
|
||||
// FIXME(effects) do we want to look at where clauses to get some
|
||||
// clue for the case where generic types are being used?
|
||||
let Some(kind) = ty::EffectKind::try_from_ty(cx, ty) else {
|
||||
return Err(NoSolution);
|
||||
};
|
||||
|
||||
let Some(result) = ty::EffectKind::min(min, kind) else {
|
||||
let Some(result) = ty::EffectKind::intersection(min, kind) else {
|
||||
return Err(NoSolution);
|
||||
};
|
||||
|
||||
|
@ -703,7 +703,7 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
fn consider_builtin_effects_min_candidate(
|
||||
fn consider_builtin_effects_intersection_candidate(
|
||||
ecx: &mut EvalCtxt<'_, D>,
|
||||
goal: Goal<I, Self>,
|
||||
) -> Result<Candidate<I>, NoSolution> {
|
||||
@ -732,7 +732,7 @@ where
|
||||
return Err(NoSolution);
|
||||
};
|
||||
|
||||
let Some(result) = ty::EffectKind::min(min, kind) else {
|
||||
let Some(result) = ty::EffectKind::intersection(min, kind) else {
|
||||
return Err(NoSolution);
|
||||
};
|
||||
|
||||
|
@ -195,9 +195,9 @@ symbols! {
|
||||
DoubleEndedIterator,
|
||||
Duration,
|
||||
EffectsCompat,
|
||||
EffectsIntersection,
|
||||
EffectsIntersectionOutput,
|
||||
EffectsMaybe,
|
||||
EffectsMin,
|
||||
EffectsMinOutput,
|
||||
EffectsNoRuntime,
|
||||
EffectsRuntime,
|
||||
EffectsTyCompat,
|
||||
|
@ -184,12 +184,10 @@ fn associated_type_for_effects(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<De
|
||||
if !tcx.features().effects {
|
||||
return None;
|
||||
}
|
||||
match tcx.def_kind(def_id) {
|
||||
let (feed, parent_did) = match tcx.def_kind(def_id) {
|
||||
DefKind::Trait => {
|
||||
let trait_def_id = def_id;
|
||||
let Some(attr) = tcx.get_attr(def_id, sym::const_trait) else {
|
||||
return None;
|
||||
};
|
||||
let attr = tcx.get_attr(def_id, sym::const_trait)?;
|
||||
|
||||
let span = attr.span;
|
||||
let trait_assoc_ty = tcx.at(span).create_def(trait_def_id, kw::Empty, DefKind::AssocTy);
|
||||
@ -197,8 +195,6 @@ fn associated_type_for_effects(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<De
|
||||
let local_def_id = trait_assoc_ty.def_id();
|
||||
let def_id = local_def_id.to_def_id();
|
||||
|
||||
trait_assoc_ty.feed_hir();
|
||||
|
||||
// Copy span of the attribute.
|
||||
trait_assoc_ty.def_ident_span(Some(span));
|
||||
|
||||
@ -213,47 +209,20 @@ fn associated_type_for_effects(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<De
|
||||
is_effects_desugaring: true,
|
||||
});
|
||||
|
||||
// visibility is public.
|
||||
trait_assoc_ty.visibility(ty::Visibility::Public);
|
||||
|
||||
// No default type
|
||||
trait_assoc_ty.defaultness(hir::Defaultness::Default { has_value: false });
|
||||
|
||||
trait_assoc_ty.is_type_alias_impl_trait(false);
|
||||
|
||||
// Copy generics_of of the trait, making the trait as parent.
|
||||
trait_assoc_ty.generics_of({
|
||||
let parent_generics = tcx.generics_of(trait_def_id);
|
||||
let parent_count = parent_generics.parent_count + parent_generics.own_params.len();
|
||||
|
||||
ty::Generics {
|
||||
parent: Some(trait_def_id.to_def_id()),
|
||||
parent_count,
|
||||
own_params: vec![],
|
||||
param_def_id_to_index: parent_generics.param_def_id_to_index.clone(),
|
||||
has_self: false,
|
||||
has_late_bound_regions: None,
|
||||
host_effect_index: parent_generics.host_effect_index,
|
||||
}
|
||||
});
|
||||
|
||||
trait_assoc_ty.explicit_item_bounds(ty::EarlyBinder::bind(&[]));
|
||||
trait_assoc_ty.explicit_item_super_predicates(ty::EarlyBinder::bind(&[]));
|
||||
|
||||
// There are no inferred outlives for the synthesized associated type.
|
||||
trait_assoc_ty.inferred_outlives_of(&[]);
|
||||
|
||||
Some(def_id)
|
||||
(trait_assoc_ty, trait_def_id)
|
||||
}
|
||||
DefKind::Impl { .. } => {
|
||||
let impl_def_id = def_id;
|
||||
let Some(trait_id) = tcx.trait_id_of_impl(def_id.to_def_id()) else { return None };
|
||||
let trait_id = tcx.trait_id_of_impl(def_id.to_def_id())?;
|
||||
|
||||
// first get the DefId of the assoc type on the trait, if there is not,
|
||||
// then we don't need to generate it on the impl.
|
||||
let Some(trait_assoc_id) = tcx.associated_type_for_effects(trait_id) else {
|
||||
return None;
|
||||
};
|
||||
let trait_assoc_id = tcx.associated_type_for_effects(trait_id)?;
|
||||
|
||||
// FIXME(effects): span
|
||||
let span = tcx.def_ident_span(def_id).unwrap();
|
||||
@ -263,8 +232,6 @@ fn associated_type_for_effects(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<De
|
||||
let local_def_id = impl_assoc_ty.def_id();
|
||||
let def_id = local_def_id.to_def_id();
|
||||
|
||||
impl_assoc_ty.feed_hir();
|
||||
|
||||
impl_assoc_ty.def_ident_span(Some(span));
|
||||
|
||||
impl_assoc_ty.associated_item(ty::AssocItem {
|
||||
@ -278,9 +245,6 @@ fn associated_type_for_effects(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<De
|
||||
is_effects_desugaring: true,
|
||||
});
|
||||
|
||||
// visibility is public.
|
||||
impl_assoc_ty.visibility(ty::Visibility::Public);
|
||||
|
||||
// no default value.
|
||||
impl_assoc_ty.defaultness(hir::Defaultness::Final);
|
||||
|
||||
@ -298,36 +262,41 @@ fn associated_type_for_effects(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<De
|
||||
ty::GenericArgs::empty(),
|
||||
)));
|
||||
|
||||
// Copy generics_of of the impl, making the impl as parent.
|
||||
impl_assoc_ty.generics_of({
|
||||
let parent_generics = tcx.generics_of(impl_def_id);
|
||||
let parent_count = parent_generics.parent_count + parent_generics.own_params.len();
|
||||
|
||||
ty::Generics {
|
||||
parent: Some(impl_def_id.to_def_id()),
|
||||
parent_count,
|
||||
own_params: vec![],
|
||||
param_def_id_to_index: parent_generics.param_def_id_to_index.clone(),
|
||||
has_self: false,
|
||||
has_late_bound_regions: None,
|
||||
host_effect_index: parent_generics.host_effect_index,
|
||||
}
|
||||
});
|
||||
|
||||
// impl_assoc_ty.explicit_item_bounds(ty::EarlyBinder::bind(&[]));
|
||||
impl_assoc_ty.explicit_item_super_predicates(ty::EarlyBinder::bind(&[]));
|
||||
|
||||
// There are no inferred outlives for the synthesized associated type.
|
||||
impl_assoc_ty.inferred_outlives_of(&[]);
|
||||
|
||||
Some(def_id)
|
||||
(impl_assoc_ty, impl_def_id)
|
||||
}
|
||||
def_kind => bug!(
|
||||
"associated_type_for_effects: {:?} should be Trait or Impl but is {:?}",
|
||||
def_id,
|
||||
def_kind
|
||||
),
|
||||
}
|
||||
};
|
||||
|
||||
feed.feed_hir();
|
||||
|
||||
// visibility is public.
|
||||
feed.visibility(ty::Visibility::Public);
|
||||
|
||||
// Copy generics_of of the trait/impl, making the trait/impl as parent.
|
||||
feed.generics_of({
|
||||
let parent_generics = tcx.generics_of(parent_did);
|
||||
let parent_count = parent_generics.parent_count + parent_generics.own_params.len();
|
||||
|
||||
ty::Generics {
|
||||
parent: Some(parent_did.to_def_id()),
|
||||
parent_count,
|
||||
own_params: vec![],
|
||||
param_def_id_to_index: parent_generics.param_def_id_to_index.clone(),
|
||||
has_self: false,
|
||||
has_late_bound_regions: None,
|
||||
host_effect_index: parent_generics.host_effect_index,
|
||||
}
|
||||
});
|
||||
feed.explicit_item_super_predicates(ty::EarlyBinder::bind(&[]));
|
||||
|
||||
// There are no inferred outlives for the synthesized associated type.
|
||||
feed.inferred_outlives_of(&[]);
|
||||
|
||||
Some(feed.def_id().to_def_id())
|
||||
}
|
||||
|
||||
/// Given an `fn_def_id` of a trait or a trait implementation:
|
||||
|
@ -44,7 +44,10 @@ impl EffectKind {
|
||||
I::Ty::new_adt(tcx, tcx.adt_def(self.to_def_id(tcx)), Default::default())
|
||||
}
|
||||
|
||||
pub fn min(a: Self, b: Self) -> Option<Self> {
|
||||
/// Returns an intersection between two effect kinds. If one effect kind
|
||||
/// is more permissive than the other (e.g. `Maybe` vs `Runtime`), this
|
||||
/// returns the less permissive effect kind (`Runtime`).
|
||||
pub fn intersection(a: Self, b: Self) -> Option<Self> {
|
||||
use EffectKind::*;
|
||||
match (a, b) {
|
||||
(Maybe, x) | (x, Maybe) => Some(x),
|
||||
|
@ -17,9 +17,9 @@ pub enum TraitSolverLangItem {
|
||||
Destruct,
|
||||
DiscriminantKind,
|
||||
DynMetadata,
|
||||
EffectsIntersection,
|
||||
EffectsIntersectionOutput,
|
||||
EffectsMaybe,
|
||||
EffectsMin,
|
||||
EffectsMinOutput,
|
||||
EffectsNoRuntime,
|
||||
EffectsRuntime,
|
||||
FnPtrTrait,
|
||||
|
@ -1062,9 +1062,14 @@ pub mod effects {
|
||||
impl<T: ?Sized> TyCompat<T> for Maybe {}
|
||||
impl<T: ?Sized> TyCompat<Maybe> for T {}
|
||||
|
||||
#[lang = "EffectsMin"]
|
||||
pub trait Min {
|
||||
#[lang = "EffectsMinOutput"]
|
||||
#[lang = "EffectsIntersection"]
|
||||
pub trait Intersection {
|
||||
#[lang = "EffectsIntersectionOutput"]
|
||||
type Output: ?Sized;
|
||||
}
|
||||
|
||||
// FIXME(effects): remove this after next trait solver lands
|
||||
impl Intersection for () {
|
||||
type Output = Maybe;
|
||||
}
|
||||
}
|
||||
|
@ -104,15 +104,18 @@ fn main() {}
|
||||
|
||||
struct D;
|
||||
|
||||
/* FIXME(effects)
|
||||
impl const Drop for D {
|
||||
fn drop(&mut self) {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Lint this, since it can be dropped in const contexts
|
||||
// FIXME(effects)
|
||||
fn d(this: D) {}
|
||||
const fn d(this: D) {}
|
||||
//~^ ERROR: this could be a `const fn`
|
||||
|
||||
mod msrv {
|
||||
struct Foo(*const u8, &'static u8);
|
||||
|
@ -161,6 +161,11 @@ error: this could be a `const fn`
|
||||
|
|
||||
LL | fn d(this: D) {}
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: make the function `const`
|
||||
|
|
||||
LL | const fn d(this: D) {}
|
||||
| +++++
|
||||
|
||||
error: this could be a `const fn`
|
||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:125:9
|
||||
|
@ -126,10 +126,10 @@ pub mod effects {
|
||||
#[stable(feature = "minicore", since = "1.0.0")]
|
||||
impl<T: ?Sized> TyCompat<Maybe> for T {}
|
||||
|
||||
#[lang = "EffectsMin"]
|
||||
#[lang = "EffectsIntersection"]
|
||||
#[stable(feature = "minicore", since = "1.0.0")]
|
||||
pub trait Min {
|
||||
#[lang = "EffectsMinOutput"]
|
||||
pub trait Intersection {
|
||||
#[lang = "EffectsIntersectionOutput"]
|
||||
#[stable(feature = "minicore", since = "1.0.0")]
|
||||
type Output: ?Sized;
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
//@ check-pass
|
||||
//@ compile-flags: -Znext-solver
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(const_trait_impl, effects)]
|
||||
|
@ -1,5 +1,7 @@
|
||||
// FIXME(effects) check-pass
|
||||
//@ known-bug: #110395
|
||||
//@ compile-flags: -Znext-solver
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(const_trait_impl, effects)]
|
||||
|
||||
#[const_trait]
|
||||
|
@ -1,20 +1,11 @@
|
||||
warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/super-traits.rs:3:30
|
||||
|
|
||||
LL | #![feature(const_trait_impl, effects)]
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0277]: the trait bound `Foo::{synthetic#0}: ~const Compat` is not satisfied
|
||||
--> $DIR/super-traits.rs:21:7
|
||||
--> $DIR/super-traits.rs:23:7
|
||||
|
|
||||
LL | t.a();
|
||||
| ^ the trait `~const Compat` is not implemented for `Foo::{synthetic#0}`
|
||||
|
|
||||
note: required by a bound in `Foo::a`
|
||||
--> $DIR/super-traits.rs:5:1
|
||||
--> $DIR/super-traits.rs:7:1
|
||||
|
|
||||
LL | #[const_trait]
|
||||
| ^^^^^^^^^^^^^^ required by this bound in `Foo::a`
|
||||
@ -26,6 +17,6 @@ help: consider further restricting the associated type
|
||||
LL | const fn foo<T: ~const Bar>(t: &T) where Foo::{synthetic#0}: ~const Compat {
|
||||
| +++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
Loading…
Reference in New Issue
Block a user