mirror of https://github.com/rust-lang/rust.git
Auto merge of #120639 - fee1-dead-contrib:new-effects-desugaring, r=oli-obk
Implement new effects desugaring cc `@rust-lang/project-const-traits.` Will write down notes once I have finished. * [x] See if we want `T: Tr` to desugar into `T: Tr, T::Effects: Compat<true>` * [x] Fix ICEs on `type Assoc: ~const Tr` and `type Assoc<T: ~const Tr>` * [ ] add types and traits to minicore test * [ ] update rustc-dev-guide Fixes #119717 Fixes #123664 Fixes #124857 Fixes #126148
This commit is contained in:
commit
ba1d7f4a08
|
@ -103,7 +103,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
ParamMode::Optional,
|
ParamMode::Optional,
|
||||||
ParenthesizedGenericArgs::Err,
|
ParenthesizedGenericArgs::Err,
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||||
None,
|
|
||||||
// Method calls can't have bound modifiers
|
// Method calls can't have bound modifiers
|
||||||
None,
|
None,
|
||||||
));
|
));
|
||||||
|
|
|
@ -56,7 +56,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
||||||
owner: NodeId,
|
owner: NodeId,
|
||||||
f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>,
|
f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>,
|
||||||
) {
|
) {
|
||||||
let mut lctx = LoweringContext::new(self.tcx, self.resolver);
|
let mut lctx = LoweringContext::new(self.tcx, self.resolver, self.ast_index);
|
||||||
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
|
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
|
||||||
|
|
||||||
for (def_id, info) in lctx.children {
|
for (def_id, info) in lctx.children {
|
||||||
|
@ -190,6 +190,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let (generics, (ty, body_id)) = self.lower_generics(
|
let (generics, (ty, body_id)) = self.lower_generics(
|
||||||
generics,
|
generics,
|
||||||
Const::No,
|
Const::No,
|
||||||
|
false,
|
||||||
id,
|
id,
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||||
|this| {
|
|this| {
|
||||||
|
@ -221,7 +222,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
|
|
||||||
let itctx = ImplTraitContext::Universal;
|
let itctx = ImplTraitContext::Universal;
|
||||||
let (generics, decl) =
|
let (generics, decl) =
|
||||||
this.lower_generics(generics, header.constness, id, itctx, |this| {
|
this.lower_generics(generics, header.constness, false, id, itctx, |this| {
|
||||||
this.lower_fn_decl(
|
this.lower_fn_decl(
|
||||||
decl,
|
decl,
|
||||||
id,
|
id,
|
||||||
|
@ -265,6 +266,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let (generics, ty) = self.lower_generics(
|
let (generics, ty) = self.lower_generics(
|
||||||
&generics,
|
&generics,
|
||||||
Const::No,
|
Const::No,
|
||||||
|
false,
|
||||||
id,
|
id,
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||||
|this| match ty {
|
|this| match ty {
|
||||||
|
@ -293,6 +295,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let (generics, variants) = self.lower_generics(
|
let (generics, variants) = self.lower_generics(
|
||||||
generics,
|
generics,
|
||||||
Const::No,
|
Const::No,
|
||||||
|
false,
|
||||||
id,
|
id,
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||||
|this| {
|
|this| {
|
||||||
|
@ -307,6 +310,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let (generics, struct_def) = self.lower_generics(
|
let (generics, struct_def) = self.lower_generics(
|
||||||
generics,
|
generics,
|
||||||
Const::No,
|
Const::No,
|
||||||
|
false,
|
||||||
id,
|
id,
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||||
|this| this.lower_variant_data(hir_id, struct_def),
|
|this| this.lower_variant_data(hir_id, struct_def),
|
||||||
|
@ -317,6 +321,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let (generics, vdata) = self.lower_generics(
|
let (generics, vdata) = self.lower_generics(
|
||||||
generics,
|
generics,
|
||||||
Const::No,
|
Const::No,
|
||||||
|
false,
|
||||||
id,
|
id,
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||||
|this| this.lower_variant_data(hir_id, vdata),
|
|this| this.lower_variant_data(hir_id, vdata),
|
||||||
|
@ -348,12 +353,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
// parent lifetime.
|
// parent lifetime.
|
||||||
let itctx = ImplTraitContext::Universal;
|
let itctx = ImplTraitContext::Universal;
|
||||||
let (generics, (trait_ref, lowered_ty)) =
|
let (generics, (trait_ref, lowered_ty)) =
|
||||||
self.lower_generics(ast_generics, *constness, id, itctx, |this| {
|
self.lower_generics(ast_generics, Const::No, false, id, itctx, |this| {
|
||||||
let modifiers = TraitBoundModifiers {
|
let modifiers = TraitBoundModifiers {
|
||||||
constness: match *constness {
|
constness: BoundConstness::Never,
|
||||||
Const::Yes(span) => BoundConstness::Maybe(span),
|
|
||||||
Const::No => BoundConstness::Never,
|
|
||||||
},
|
|
||||||
asyncness: BoundAsyncness::Normal,
|
asyncness: BoundAsyncness::Normal,
|
||||||
// we don't use this in bound lowering
|
// we don't use this in bound lowering
|
||||||
polarity: BoundPolarity::Positive,
|
polarity: BoundPolarity::Positive,
|
||||||
|
@ -389,6 +391,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(*s)),
|
ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(*s)),
|
||||||
};
|
};
|
||||||
hir::ItemKind::Impl(self.arena.alloc(hir::Impl {
|
hir::ItemKind::Impl(self.arena.alloc(hir::Impl {
|
||||||
|
constness: self.lower_constness(*constness),
|
||||||
safety: self.lower_safety(*safety, hir::Safety::Safe),
|
safety: self.lower_safety(*safety, hir::Safety::Safe),
|
||||||
polarity,
|
polarity,
|
||||||
defaultness,
|
defaultness,
|
||||||
|
@ -400,15 +403,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
ItemKind::Trait(box Trait { is_auto, safety, generics, bounds, items }) => {
|
ItemKind::Trait(box Trait { is_auto, safety, generics, bounds, items }) => {
|
||||||
// FIXME(const_trait_impl, effects, fee1-dead) this should be simplified if possible
|
|
||||||
let constness = attrs
|
|
||||||
.unwrap_or(&[])
|
|
||||||
.iter()
|
|
||||||
.find(|x| x.has_name(sym::const_trait))
|
|
||||||
.map_or(Const::No, |x| Const::Yes(x.span));
|
|
||||||
let (generics, (safety, items, bounds)) = self.lower_generics(
|
let (generics, (safety, items, bounds)) = self.lower_generics(
|
||||||
generics,
|
generics,
|
||||||
constness,
|
Const::No,
|
||||||
|
false,
|
||||||
id,
|
id,
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||||
|this| {
|
|this| {
|
||||||
|
@ -429,6 +427,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let (generics, bounds) = self.lower_generics(
|
let (generics, bounds) = self.lower_generics(
|
||||||
generics,
|
generics,
|
||||||
Const::No,
|
Const::No,
|
||||||
|
false,
|
||||||
id,
|
id,
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||||
|this| {
|
|this| {
|
||||||
|
@ -609,30 +608,45 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
// This is used to track which lifetimes have already been defined,
|
// This is used to track which lifetimes have already been defined,
|
||||||
// and which need to be replicated when lowering an async fn.
|
// and which need to be replicated when lowering an async fn.
|
||||||
|
|
||||||
let generics = match parent_hir.node().expect_item().kind {
|
let parent_item = parent_hir.node().expect_item();
|
||||||
|
let constness = match parent_item.kind {
|
||||||
hir::ItemKind::Impl(impl_) => {
|
hir::ItemKind::Impl(impl_) => {
|
||||||
self.is_in_trait_impl = impl_.of_trait.is_some();
|
self.is_in_trait_impl = impl_.of_trait.is_some();
|
||||||
&impl_.generics
|
// N.B. the impl should always lower to methods that have `const host: bool` params if the trait
|
||||||
|
// is const. It doesn't matter whether the `impl` itself is const. Disallowing const fn from
|
||||||
|
// calling non-const impls are done through associated types.
|
||||||
|
if let Some(def_id) = impl_.of_trait.and_then(|tr| tr.trait_def_id()) {
|
||||||
|
if let Some(local_def) = def_id.as_local() {
|
||||||
|
match &self.ast_index[local_def] {
|
||||||
|
AstOwner::Item(ast::Item { attrs, .. }) => attrs
|
||||||
|
.iter()
|
||||||
|
.find(|attr| attr.has_name(sym::const_trait))
|
||||||
|
.map_or(Const::No, |attr| Const::Yes(attr.span)),
|
||||||
|
_ => Const::No,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.tcx
|
||||||
|
.get_attr(def_id, sym::const_trait)
|
||||||
|
.map_or(Const::No, |attr| Const::Yes(attr.span))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Const::No
|
||||||
|
}
|
||||||
}
|
}
|
||||||
hir::ItemKind::Trait(_, _, generics, _, _) => generics,
|
hir::ItemKind::Trait(_, _, _, _, _) => parent_hir
|
||||||
|
.attrs
|
||||||
|
.get(parent_item.hir_id().local_id)
|
||||||
|
.iter()
|
||||||
|
.find(|attr| attr.has_name(sym::const_trait))
|
||||||
|
.map_or(Const::No, |attr| Const::Yes(attr.span)),
|
||||||
kind => {
|
kind => {
|
||||||
span_bug!(item.span, "assoc item has unexpected kind of parent: {}", kind.descr())
|
span_bug!(item.span, "assoc item has unexpected kind of parent: {}", kind.descr())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.tcx.features().effects {
|
|
||||||
self.host_param_id = generics
|
|
||||||
.params
|
|
||||||
.iter()
|
|
||||||
.find(|param| {
|
|
||||||
matches!(param.kind, hir::GenericParamKind::Const { is_host_effect: true, .. })
|
|
||||||
})
|
|
||||||
.map(|param| param.def_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
match ctxt {
|
match ctxt {
|
||||||
AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item)),
|
AssocCtxt::Trait => hir::OwnerNode::TraitItem(self.lower_trait_item(item, constness)),
|
||||||
AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item)),
|
AssocCtxt::Impl => hir::OwnerNode::ImplItem(self.lower_impl_item(item, constness)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -648,7 +662,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let fdec = &sig.decl;
|
let fdec = &sig.decl;
|
||||||
let itctx = ImplTraitContext::Universal;
|
let itctx = ImplTraitContext::Universal;
|
||||||
let (generics, (fn_dec, fn_args)) =
|
let (generics, (fn_dec, fn_args)) =
|
||||||
self.lower_generics(generics, Const::No, i.id, itctx, |this| {
|
self.lower_generics(generics, Const::No, false, i.id, itctx, |this| {
|
||||||
(
|
(
|
||||||
// Disallow `impl Trait` in foreign items.
|
// Disallow `impl Trait` in foreign items.
|
||||||
this.lower_fn_decl(
|
this.lower_fn_decl(
|
||||||
|
@ -765,7 +779,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> {
|
fn lower_trait_item(
|
||||||
|
&mut self,
|
||||||
|
i: &AssocItem,
|
||||||
|
trait_constness: Const,
|
||||||
|
) -> &'hir hir::TraitItem<'hir> {
|
||||||
let hir_id = self.lower_node_id(i.id);
|
let hir_id = self.lower_node_id(i.id);
|
||||||
self.lower_attrs(hir_id, &i.attrs);
|
self.lower_attrs(hir_id, &i.attrs);
|
||||||
let trait_item_def_id = hir_id.expect_owner();
|
let trait_item_def_id = hir_id.expect_owner();
|
||||||
|
@ -775,6 +793,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let (generics, kind) = self.lower_generics(
|
let (generics, kind) = self.lower_generics(
|
||||||
generics,
|
generics,
|
||||||
Const::No,
|
Const::No,
|
||||||
|
false,
|
||||||
i.id,
|
i.id,
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||||
|this| {
|
|this| {
|
||||||
|
@ -795,6 +814,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
i.id,
|
i.id,
|
||||||
FnDeclKind::Trait,
|
FnDeclKind::Trait,
|
||||||
sig.header.coroutine_kind,
|
sig.header.coroutine_kind,
|
||||||
|
trait_constness,
|
||||||
);
|
);
|
||||||
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
|
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
|
||||||
}
|
}
|
||||||
|
@ -813,6 +833,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
i.id,
|
i.id,
|
||||||
FnDeclKind::Trait,
|
FnDeclKind::Trait,
|
||||||
sig.header.coroutine_kind,
|
sig.header.coroutine_kind,
|
||||||
|
trait_constness,
|
||||||
);
|
);
|
||||||
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true)
|
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true)
|
||||||
}
|
}
|
||||||
|
@ -822,6 +843,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let (generics, kind) = self.lower_generics(
|
let (generics, kind) = self.lower_generics(
|
||||||
&generics,
|
&generics,
|
||||||
Const::No,
|
Const::No,
|
||||||
|
false,
|
||||||
i.id,
|
i.id,
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||||
|this| {
|
|this| {
|
||||||
|
@ -894,7 +916,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
self.expr(span, hir::ExprKind::Err(guar))
|
self.expr(span, hir::ExprKind::Err(guar))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> {
|
fn lower_impl_item(
|
||||||
|
&mut self,
|
||||||
|
i: &AssocItem,
|
||||||
|
constness_of_trait: Const,
|
||||||
|
) -> &'hir hir::ImplItem<'hir> {
|
||||||
// Since `default impl` is not yet implemented, this is always true in impls.
|
// Since `default impl` is not yet implemented, this is always true in impls.
|
||||||
let has_value = true;
|
let has_value = true;
|
||||||
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
|
let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value);
|
||||||
|
@ -905,6 +931,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics(
|
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics(
|
||||||
generics,
|
generics,
|
||||||
Const::No,
|
Const::No,
|
||||||
|
false,
|
||||||
i.id,
|
i.id,
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||||
|this| {
|
|this| {
|
||||||
|
@ -930,6 +957,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
i.id,
|
i.id,
|
||||||
if self.is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent },
|
if self.is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent },
|
||||||
sig.header.coroutine_kind,
|
sig.header.coroutine_kind,
|
||||||
|
constness_of_trait,
|
||||||
);
|
);
|
||||||
|
|
||||||
(generics, hir::ImplItemKind::Fn(sig, body_id))
|
(generics, hir::ImplItemKind::Fn(sig, body_id))
|
||||||
|
@ -940,6 +968,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
self.lower_generics(
|
self.lower_generics(
|
||||||
&generics,
|
&generics,
|
||||||
Const::No,
|
Const::No,
|
||||||
|
false,
|
||||||
i.id,
|
i.id,
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
|
||||||
|this| match ty {
|
|this| match ty {
|
||||||
|
@ -1352,15 +1381,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
id: NodeId,
|
id: NodeId,
|
||||||
kind: FnDeclKind,
|
kind: FnDeclKind,
|
||||||
coroutine_kind: Option<CoroutineKind>,
|
coroutine_kind: Option<CoroutineKind>,
|
||||||
|
parent_constness: Const,
|
||||||
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
|
) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) {
|
||||||
let header = self.lower_fn_header(sig.header);
|
let header = self.lower_fn_header(sig.header);
|
||||||
// Don't pass along the user-provided constness of trait associated functions; we don't want to
|
// Don't pass along the user-provided constness of trait associated functions; we don't want to
|
||||||
// synthesize a host effect param for them. We reject `const` on them during AST validation.
|
// synthesize a host effect param for them. We reject `const` on them during AST validation.
|
||||||
let constness = if kind == FnDeclKind::Inherent { sig.header.constness } else { Const::No };
|
let constness =
|
||||||
|
if kind == FnDeclKind::Inherent { sig.header.constness } else { parent_constness };
|
||||||
let itctx = ImplTraitContext::Universal;
|
let itctx = ImplTraitContext::Universal;
|
||||||
let (generics, decl) = self.lower_generics(generics, constness, id, itctx, |this| {
|
let (generics, decl) =
|
||||||
this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind)
|
self.lower_generics(generics, constness, kind == FnDeclKind::Impl, id, itctx, |this| {
|
||||||
});
|
this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind)
|
||||||
|
});
|
||||||
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
|
(generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1436,6 +1468,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
&mut self,
|
&mut self,
|
||||||
generics: &Generics,
|
generics: &Generics,
|
||||||
constness: Const,
|
constness: Const,
|
||||||
|
force_append_constness: bool,
|
||||||
parent_node_id: NodeId,
|
parent_node_id: NodeId,
|
||||||
itctx: ImplTraitContext,
|
itctx: ImplTraitContext,
|
||||||
f: impl FnOnce(&mut Self) -> T,
|
f: impl FnOnce(&mut Self) -> T,
|
||||||
|
@ -1496,7 +1529,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
// if the effects feature is enabled. This needs to be done before we lower where
|
// if the effects feature is enabled. This needs to be done before we lower where
|
||||||
// clauses since where clauses need to bind to the DefId of the host param
|
// clauses since where clauses need to bind to the DefId of the host param
|
||||||
let host_param_parts = if let Const::Yes(span) = constness
|
let host_param_parts = if let Const::Yes(span) = constness
|
||||||
&& self.tcx.features().effects
|
// if this comes from implementing a `const` trait, we must force constness to be appended
|
||||||
|
// to the impl item, no matter whether effects is enabled.
|
||||||
|
&& (self.tcx.features().effects || force_append_constness)
|
||||||
{
|
{
|
||||||
let span = self.lower_span(span);
|
let span = self.lower_span(span);
|
||||||
let param_node_id = self.next_node_id();
|
let param_node_id = self.next_node_id();
|
||||||
|
@ -1609,6 +1644,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
}),
|
}),
|
||||||
)),
|
)),
|
||||||
)),
|
)),
|
||||||
|
// FIXME(effects) we might not need a default.
|
||||||
default: Some(self.arena.alloc(hir::AnonConst {
|
default: Some(self.arena.alloc(hir::AnonConst {
|
||||||
def_id: anon_const,
|
def_id: anon_const,
|
||||||
hir_id: const_id,
|
hir_id: const_id,
|
||||||
|
@ -1616,6 +1652,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
span,
|
span,
|
||||||
})),
|
})),
|
||||||
is_host_effect: true,
|
is_host_effect: true,
|
||||||
|
synthetic: true,
|
||||||
},
|
},
|
||||||
colon_span: None,
|
colon_span: None,
|
||||||
pure_wrt_drop: false,
|
pure_wrt_drop: false,
|
||||||
|
|
|
@ -142,14 +142,19 @@ struct LoweringContext<'a, 'hir> {
|
||||||
generics_def_id_map: Vec<LocalDefIdMap<LocalDefId>>,
|
generics_def_id_map: Vec<LocalDefIdMap<LocalDefId>>,
|
||||||
|
|
||||||
host_param_id: Option<LocalDefId>,
|
host_param_id: Option<LocalDefId>,
|
||||||
|
ast_index: &'a IndexSlice<LocalDefId, AstOwner<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
fn new(tcx: TyCtxt<'hir>, resolver: &'a mut ResolverAstLowering) -> Self {
|
fn new(
|
||||||
|
tcx: TyCtxt<'hir>,
|
||||||
|
resolver: &'a mut ResolverAstLowering,
|
||||||
|
ast_index: &'a IndexSlice<LocalDefId, AstOwner<'a>>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
// Pseudo-globals.
|
// Pseudo-globals.
|
||||||
tcx,
|
tcx,
|
||||||
resolver: resolver,
|
resolver,
|
||||||
arena: tcx.hir_arena,
|
arena: tcx.hir_arena,
|
||||||
|
|
||||||
// HirId handling.
|
// HirId handling.
|
||||||
|
@ -185,6 +190,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
allow_async_iterator: [sym::gen_future, sym::async_iterator].into(),
|
allow_async_iterator: [sym::gen_future, sym::async_iterator].into(),
|
||||||
generics_def_id_map: Default::default(),
|
generics_def_id_map: Default::default(),
|
||||||
host_param_id: None,
|
host_param_id: None,
|
||||||
|
ast_index,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2135,7 +2141,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
param: &GenericParam,
|
param: &GenericParam,
|
||||||
source: hir::GenericParamSource,
|
source: hir::GenericParamSource,
|
||||||
) -> hir::GenericParam<'hir> {
|
) -> hir::GenericParam<'hir> {
|
||||||
let (name, kind) = self.lower_generic_param_kind(param, source);
|
let (name, kind) = self.lower_generic_param_kind(
|
||||||
|
param,
|
||||||
|
source,
|
||||||
|
attr::contains_name(¶m.attrs, sym::rustc_runtime),
|
||||||
|
);
|
||||||
|
|
||||||
let hir_id = self.lower_node_id(param.id);
|
let hir_id = self.lower_node_id(param.id);
|
||||||
self.lower_attrs(hir_id, ¶m.attrs);
|
self.lower_attrs(hir_id, ¶m.attrs);
|
||||||
|
@ -2155,6 +2165,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
&mut self,
|
&mut self,
|
||||||
param: &GenericParam,
|
param: &GenericParam,
|
||||||
source: hir::GenericParamSource,
|
source: hir::GenericParamSource,
|
||||||
|
is_host_effect: bool,
|
||||||
) -> (hir::ParamName, hir::GenericParamKind<'hir>) {
|
) -> (hir::ParamName, hir::GenericParamKind<'hir>) {
|
||||||
match ¶m.kind {
|
match ¶m.kind {
|
||||||
GenericParamKind::Lifetime => {
|
GenericParamKind::Lifetime => {
|
||||||
|
@ -2220,7 +2231,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
|
|
||||||
(
|
(
|
||||||
hir::ParamName::Plain(self.lower_ident(param.ident)),
|
hir::ParamName::Plain(self.lower_ident(param.ident)),
|
||||||
hir::GenericParamKind::Const { ty, default, is_host_effect: false },
|
hir::GenericParamKind::Const { ty, default, is_host_effect, synthetic: false },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2607,78 +2618,6 @@ struct GenericArgsCtor<'hir> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'hir> GenericArgsCtor<'hir> {
|
impl<'hir> GenericArgsCtor<'hir> {
|
||||||
fn push_constness(
|
|
||||||
&mut self,
|
|
||||||
lcx: &mut LoweringContext<'_, 'hir>,
|
|
||||||
constness: ast::BoundConstness,
|
|
||||||
) {
|
|
||||||
if !lcx.tcx.features().effects {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let (span, body) = match constness {
|
|
||||||
BoundConstness::Never => return,
|
|
||||||
BoundConstness::Always(span) => {
|
|
||||||
let span = lcx.lower_span(span);
|
|
||||||
|
|
||||||
let body = hir::ExprKind::Lit(
|
|
||||||
lcx.arena.alloc(hir::Lit { node: LitKind::Bool(false), span }),
|
|
||||||
);
|
|
||||||
|
|
||||||
(span, body)
|
|
||||||
}
|
|
||||||
BoundConstness::Maybe(span) => {
|
|
||||||
let span = lcx.lower_span(span);
|
|
||||||
|
|
||||||
let Some(host_param_id) = lcx.host_param_id else {
|
|
||||||
lcx.dcx().span_delayed_bug(
|
|
||||||
span,
|
|
||||||
"no host param id for call in const yet no errors reported",
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
let hir_id = lcx.next_id();
|
|
||||||
let res = Res::Def(DefKind::ConstParam, host_param_id.to_def_id());
|
|
||||||
let body = hir::ExprKind::Path(hir::QPath::Resolved(
|
|
||||||
None,
|
|
||||||
lcx.arena.alloc(hir::Path {
|
|
||||||
span,
|
|
||||||
res,
|
|
||||||
segments: arena_vec![
|
|
||||||
lcx;
|
|
||||||
hir::PathSegment::new(
|
|
||||||
Ident { name: sym::host, span },
|
|
||||||
hir_id,
|
|
||||||
res
|
|
||||||
)
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
));
|
|
||||||
|
|
||||||
(span, body)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let body = lcx.lower_body(|lcx| (&[], lcx.expr(span, body)));
|
|
||||||
|
|
||||||
let id = lcx.next_node_id();
|
|
||||||
let hir_id = lcx.next_id();
|
|
||||||
|
|
||||||
let def_id = lcx.create_def(
|
|
||||||
lcx.current_hir_id_owner.def_id,
|
|
||||||
id,
|
|
||||||
kw::Empty,
|
|
||||||
DefKind::AnonConst,
|
|
||||||
span,
|
|
||||||
);
|
|
||||||
|
|
||||||
lcx.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
|
|
||||||
self.args.push(hir::GenericArg::Const(hir::ConstArg {
|
|
||||||
value: lcx.arena.alloc(hir::AnonConst { def_id, hir_id, body, span }),
|
|
||||||
is_desugared_from_effects: true,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_empty(&self) -> bool {
|
fn is_empty(&self) -> bool {
|
||||||
self.args.is_empty()
|
self.args.is_empty()
|
||||||
&& self.constraints.is_empty()
|
&& self.constraints.is_empty()
|
||||||
|
|
|
@ -107,8 +107,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
param_mode,
|
param_mode,
|
||||||
parenthesized_generic_args,
|
parenthesized_generic_args,
|
||||||
itctx,
|
itctx,
|
||||||
// if this is the last segment, add constness to the trait path
|
|
||||||
if i == proj_start - 1 { modifiers.map(|m| m.constness) } else { None },
|
|
||||||
bound_modifier_allowed_features.clone(),
|
bound_modifier_allowed_features.clone(),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
@ -165,7 +163,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
ParenthesizedGenericArgs::Err,
|
ParenthesizedGenericArgs::Err,
|
||||||
itctx,
|
itctx,
|
||||||
None,
|
None,
|
||||||
None,
|
|
||||||
));
|
));
|
||||||
let qpath = hir::QPath::TypeRelative(ty, hir_segment);
|
let qpath = hir::QPath::TypeRelative(ty, hir_segment);
|
||||||
|
|
||||||
|
@ -208,7 +205,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
ParenthesizedGenericArgs::Err,
|
ParenthesizedGenericArgs::Err,
|
||||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||||
None,
|
None,
|
||||||
None,
|
|
||||||
)
|
)
|
||||||
})),
|
})),
|
||||||
span: self.lower_span(p.span),
|
span: self.lower_span(p.span),
|
||||||
|
@ -222,7 +218,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
param_mode: ParamMode,
|
param_mode: ParamMode,
|
||||||
parenthesized_generic_args: ParenthesizedGenericArgs,
|
parenthesized_generic_args: ParenthesizedGenericArgs,
|
||||||
itctx: ImplTraitContext,
|
itctx: ImplTraitContext,
|
||||||
constness: Option<ast::BoundConstness>,
|
|
||||||
// Additional features ungated with a bound modifier like `async`.
|
// Additional features ungated with a bound modifier like `async`.
|
||||||
// This is passed down to the implicit associated type binding in
|
// This is passed down to the implicit associated type binding in
|
||||||
// parenthesized bounds.
|
// parenthesized bounds.
|
||||||
|
@ -289,10 +284,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(constness) = constness {
|
|
||||||
generic_args.push_constness(self, constness);
|
|
||||||
}
|
|
||||||
|
|
||||||
let has_lifetimes =
|
let has_lifetimes =
|
||||||
generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
|
generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
|
||||||
|
|
||||||
|
|
|
@ -42,10 +42,7 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
|
||||||
| hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => {
|
| hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => {
|
||||||
hir::Constness::Const
|
hir::Constness::Const
|
||||||
}
|
}
|
||||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }) => tcx
|
hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.constness,
|
||||||
.generics_of(def_id)
|
|
||||||
.host_effect_index
|
|
||||||
.map_or(hir::Constness::NotConst, |_| hir::Constness::Const),
|
|
||||||
hir::Node::ForeignItem(hir::ForeignItem { kind: hir::ForeignItemKind::Fn(..), .. }) => {
|
hir::Node::ForeignItem(hir::ForeignItem { kind: hir::ForeignItemKind::Fn(..), .. }) => {
|
||||||
// Intrinsics use `rustc_const_{un,}stable` attributes to indicate constness. All other
|
// Intrinsics use `rustc_const_{un,}stable` attributes to indicate constness. All other
|
||||||
// foreign items cannot be evaluated at compile-time.
|
// foreign items cannot be evaluated at compile-time.
|
||||||
|
|
|
@ -833,6 +833,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||||
rustc_const_panic_str, Normal, template!(Word), WarnFollowing,
|
rustc_const_panic_str, Normal, template!(Word), WarnFollowing,
|
||||||
EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
|
EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
|
||||||
),
|
),
|
||||||
|
rustc_attr!(
|
||||||
|
rustc_runtime, Normal, template!(Word), WarnFollowing,
|
||||||
|
EncodeCrossCrate::No, INTERNAL_UNSTABLE
|
||||||
|
),
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// Internal attributes, Layout related:
|
// Internal attributes, Layout related:
|
||||||
|
|
|
@ -526,6 +526,7 @@ pub enum GenericParamKind<'hir> {
|
||||||
/// Optional default value for the const generic param
|
/// Optional default value for the const generic param
|
||||||
default: Option<&'hir AnonConst>,
|
default: Option<&'hir AnonConst>,
|
||||||
is_host_effect: bool,
|
is_host_effect: bool,
|
||||||
|
synthetic: bool,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3364,6 +3365,7 @@ pub enum ItemKind<'hir> {
|
||||||
/// Refer to [`ImplItem`] for an associated item within an impl block.
|
/// Refer to [`ImplItem`] for an associated item within an impl block.
|
||||||
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
#[derive(Debug, Clone, Copy, HashStable_Generic)]
|
||||||
pub struct Impl<'hir> {
|
pub struct Impl<'hir> {
|
||||||
|
pub constness: Constness,
|
||||||
pub safety: Safety,
|
pub safety: Safety,
|
||||||
pub polarity: ImplPolarity,
|
pub polarity: ImplPolarity,
|
||||||
pub defaultness: Defaultness,
|
pub defaultness: Defaultness,
|
||||||
|
|
|
@ -543,6 +543,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
|
||||||
try_visit!(visitor.visit_enum_def(enum_definition, item.hir_id()));
|
try_visit!(visitor.visit_enum_def(enum_definition, item.hir_id()));
|
||||||
}
|
}
|
||||||
ItemKind::Impl(Impl {
|
ItemKind::Impl(Impl {
|
||||||
|
constness: _,
|
||||||
safety: _,
|
safety: _,
|
||||||
defaultness: _,
|
defaultness: _,
|
||||||
polarity: _,
|
polarity: _,
|
||||||
|
@ -915,7 +916,7 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(
|
||||||
match param.kind {
|
match param.kind {
|
||||||
GenericParamKind::Lifetime { .. } => {}
|
GenericParamKind::Lifetime { .. } => {}
|
||||||
GenericParamKind::Type { ref default, .. } => visit_opt!(visitor, visit_ty, default),
|
GenericParamKind::Type { ref default, .. } => visit_opt!(visitor, visit_ty, default),
|
||||||
GenericParamKind::Const { ref ty, ref default, is_host_effect: _ } => {
|
GenericParamKind::Const { ref ty, ref default, is_host_effect: _, synthetic: _ } => {
|
||||||
try_visit!(visitor.visit_ty(ty));
|
try_visit!(visitor.visit_ty(ty));
|
||||||
if let Some(ref default) = default {
|
if let Some(ref default) = default {
|
||||||
try_visit!(visitor.visit_const_param_default(param.hir_id, default));
|
try_visit!(visitor.visit_const_param_default(param.hir_id, default));
|
||||||
|
|
|
@ -393,6 +393,14 @@ language_item_table! {
|
||||||
|
|
||||||
String, sym::String, string, Target::Struct, GenericRequirement::None;
|
String, sym::String, string, Target::Struct, GenericRequirement::None;
|
||||||
CStr, sym::CStr, c_str, Target::Struct, GenericRequirement::None;
|
CStr, sym::CStr, c_str, Target::Struct, GenericRequirement::None;
|
||||||
|
|
||||||
|
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;
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum GenericRequirement {
|
pub enum GenericRequirement {
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
//! Bounds are restrictions applied to some types after they've been lowered from the HIR to the
|
//! Bounds are restrictions applied to some types after they've been lowered from the HIR to the
|
||||||
//! [`rustc_middle::ty`] form.
|
//! [`rustc_middle::ty`] form.
|
||||||
|
|
||||||
|
use rustc_data_structures::fx::FxIndexMap;
|
||||||
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::LangItem;
|
use rustc_hir::LangItem;
|
||||||
|
use rustc_middle::ty::fold::FnMutDelegate;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt, Upcast};
|
use rustc_middle::ty::{self, Ty, TyCtxt, Upcast};
|
||||||
use rustc_span::Span;
|
use rustc_span::def_id::DefId;
|
||||||
|
use rustc_span::{sym, Span};
|
||||||
|
|
||||||
/// Collects together a list of type bounds. These lists of bounds occur in many places
|
/// Collects together a list of type bounds. These lists of bounds occur in many places
|
||||||
/// in Rust's syntax:
|
/// in Rust's syntax:
|
||||||
|
@ -24,6 +28,7 @@ use rustc_span::Span;
|
||||||
#[derive(Default, PartialEq, Eq, Clone, Debug)]
|
#[derive(Default, PartialEq, Eq, Clone, Debug)]
|
||||||
pub struct Bounds<'tcx> {
|
pub struct Bounds<'tcx> {
|
||||||
clauses: Vec<(ty::Clause<'tcx>, Span)>,
|
clauses: Vec<(ty::Clause<'tcx>, Span)>,
|
||||||
|
effects_min_tys: FxIndexMap<Ty<'tcx>, Span>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Bounds<'tcx> {
|
impl<'tcx> Bounds<'tcx> {
|
||||||
|
@ -40,12 +45,14 @@ impl<'tcx> Bounds<'tcx> {
|
||||||
pub fn push_trait_bound(
|
pub fn push_trait_bound(
|
||||||
&mut self,
|
&mut self,
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
defining_def_id: DefId,
|
||||||
|
bound_trait_ref: ty::PolyTraitRef<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
polarity: ty::PredicatePolarity,
|
polarity: ty::PredicatePolarity,
|
||||||
|
constness: ty::BoundConstness,
|
||||||
) {
|
) {
|
||||||
let clause = (
|
let clause = (
|
||||||
trait_ref
|
bound_trait_ref
|
||||||
.map_bound(|trait_ref| {
|
.map_bound(|trait_ref| {
|
||||||
ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity })
|
ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity })
|
||||||
})
|
})
|
||||||
|
@ -53,11 +60,98 @@ impl<'tcx> Bounds<'tcx> {
|
||||||
span,
|
span,
|
||||||
);
|
);
|
||||||
// FIXME(-Znext-solver): We can likely remove this hack once the new trait solver lands.
|
// FIXME(-Znext-solver): We can likely remove this hack once the new trait solver lands.
|
||||||
if tcx.is_lang_item(trait_ref.def_id(), LangItem::Sized) {
|
if tcx.is_lang_item(bound_trait_ref.def_id(), LangItem::Sized) {
|
||||||
self.clauses.insert(0, clause);
|
self.clauses.insert(0, clause);
|
||||||
} else {
|
} else {
|
||||||
self.clauses.push(clause);
|
self.clauses.push(clause);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !tcx.features().effects {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 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.
|
||||||
|
let compat_val = match (tcx.def_kind(defining_def_id), constness) {
|
||||||
|
// FIXME(effects): revisit the correctness of this
|
||||||
|
(_, ty::BoundConstness::Const) => tcx.consts.false_,
|
||||||
|
// body owners that can have trait bounds
|
||||||
|
(DefKind::Const | DefKind::Fn | DefKind::AssocFn, ty::BoundConstness::ConstIfConst) => {
|
||||||
|
tcx.expected_host_effect_param_for_body(defining_def_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
(_, ty::BoundConstness::NotConst) => {
|
||||||
|
if !tcx.has_attr(bound_trait_ref.def_id(), sym::const_trait) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tcx.consts.true_
|
||||||
|
}
|
||||||
|
|
||||||
|
(
|
||||||
|
DefKind::Trait | DefKind::Impl { of_trait: true },
|
||||||
|
ty::BoundConstness::ConstIfConst,
|
||||||
|
) => {
|
||||||
|
// this is either a where clause on an impl/trait header or on a trait.
|
||||||
|
// push `<T as Tr>::Effects` into the set for the `Min` bound.
|
||||||
|
let Some(assoc) = tcx.associated_type_for_effects(bound_trait_ref.def_id()) else {
|
||||||
|
tcx.dcx().span_delayed_bug(span, "`~const` on trait without Effects assoc");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let ty = bound_trait_ref
|
||||||
|
.map_bound(|trait_ref| Ty::new_projection(tcx, assoc, trait_ref.args));
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
regions: &mut |_| tcx.lifetimes.re_static,
|
||||||
|
types: &mut |_| tcx.types.unit,
|
||||||
|
consts: &mut |_| unimplemented!("`~const` does not support const binders"),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
self.effects_min_tys.insert(ty, span);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// for
|
||||||
|
// ```
|
||||||
|
// trait Foo { type Bar: ~const Trait }
|
||||||
|
// ```
|
||||||
|
// ensure that `<Self::Bar as Trait>::Effects: TyCompat<Self::Effects>`.
|
||||||
|
//
|
||||||
|
// FIXME(effects) this is equality for now, which wouldn't be helpful for a non-const implementor
|
||||||
|
// that uses a `Bar` that implements `Trait` with `Maybe` effects.
|
||||||
|
(DefKind::AssocTy, ty::BoundConstness::ConstIfConst) => {
|
||||||
|
// FIXME(effects): implement this
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// probably illegal in this position.
|
||||||
|
(_, ty::BoundConstness::ConstIfConst) => {
|
||||||
|
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()],
|
||||||
|
);
|
||||||
|
self.clauses.push((bound_trait_ref.rebind(new_trait_ref).upcast(tcx), span));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_projection_bound(
|
pub fn push_projection_bound(
|
||||||
|
@ -79,7 +173,15 @@ impl<'tcx> Bounds<'tcx> {
|
||||||
self.clauses.insert(0, (trait_ref.upcast(tcx), span));
|
self.clauses.insert(0, (trait_ref.upcast(tcx), span));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clauses(&self) -> impl Iterator<Item = (ty::Clause<'tcx>, Span)> + '_ {
|
pub fn clauses(
|
||||||
|
&self,
|
||||||
|
// FIXME(effects): remove tcx
|
||||||
|
_tcx: TyCtxt<'tcx>,
|
||||||
|
) -> impl Iterator<Item = (ty::Clause<'tcx>, Span)> + '_ {
|
||||||
self.clauses.iter().cloned()
|
self.clauses.iter().cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn effects_min_tys(&self) -> impl Iterator<Item = Ty<'tcx>> + '_ {
|
||||||
|
self.effects_min_tys.keys().copied()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -879,7 +879,8 @@ pub(super) fn check_specialization_validity<'tcx>(
|
||||||
let result = opt_result.unwrap_or(Ok(()));
|
let result = opt_result.unwrap_or(Ok(()));
|
||||||
|
|
||||||
if let Err(parent_impl) = result {
|
if let Err(parent_impl) = result {
|
||||||
if !tcx.is_impl_trait_in_trait(impl_item) {
|
// FIXME(effects) the associated type from effects could be specialized
|
||||||
|
if !tcx.is_impl_trait_in_trait(impl_item) && !tcx.is_effects_desugared_assoc_ty(impl_item) {
|
||||||
report_forbidden_specialization(tcx, impl_item, parent_impl);
|
report_forbidden_specialization(tcx, impl_item, parent_impl);
|
||||||
} else {
|
} else {
|
||||||
tcx.dcx().delayed_bug(format!("parent item: {parent_impl:?} not marked as default"));
|
tcx.dcx().delayed_bug(format!("parent item: {parent_impl:?} not marked as default"));
|
||||||
|
|
|
@ -1985,10 +1985,10 @@ pub(super) fn check_type_bounds<'tcx>(
|
||||||
let infcx = tcx.infer_ctxt().build();
|
let infcx = tcx.infer_ctxt().build();
|
||||||
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
|
||||||
|
|
||||||
// A synthetic impl Trait for RPITIT desugaring has no HIR, which we currently use to get the
|
// A synthetic impl Trait for RPITIT desugaring or assoc type for effects desugaring has no HIR,
|
||||||
// span for an impl's associated type. Instead, for these, use the def_span for the synthesized
|
// which we currently use to get the span for an impl's associated type. Instead, for these,
|
||||||
// associated type.
|
// use the def_span for the synthesized associated type.
|
||||||
let impl_ty_span = if impl_ty.is_impl_trait_in_trait() {
|
let impl_ty_span = if impl_ty.is_impl_trait_in_trait() || impl_ty.is_effects_desugaring {
|
||||||
tcx.def_span(impl_ty_def_id)
|
tcx.def_span(impl_ty_def_id)
|
||||||
} else {
|
} else {
|
||||||
match tcx.hir_node_by_def_id(impl_ty_def_id) {
|
match tcx.hir_node_by_def_id(impl_ty_def_id) {
|
||||||
|
|
|
@ -913,7 +913,12 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
|
||||||
hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => Ok(()),
|
hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => Ok(()),
|
||||||
|
|
||||||
// Const parameters are well formed if their type is structural match.
|
// Const parameters are well formed if their type is structural match.
|
||||||
hir::GenericParamKind::Const { ty: hir_ty, default: _, is_host_effect: _ } => {
|
hir::GenericParamKind::Const {
|
||||||
|
ty: hir_ty,
|
||||||
|
default: _,
|
||||||
|
is_host_effect: _,
|
||||||
|
synthetic: _,
|
||||||
|
} => {
|
||||||
let ty = tcx.type_of(param.def_id).instantiate_identity();
|
let ty = tcx.type_of(param.def_id).instantiate_identity();
|
||||||
|
|
||||||
if tcx.features().adt_const_params {
|
if tcx.features().adt_const_params {
|
||||||
|
|
|
@ -1638,44 +1638,19 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTrai
|
||||||
let icx = ItemCtxt::new(tcx, def_id);
|
let icx = ItemCtxt::new(tcx, def_id);
|
||||||
let item = tcx.hir().expect_item(def_id);
|
let item = tcx.hir().expect_item(def_id);
|
||||||
let impl_ = item.expect_impl();
|
let impl_ = item.expect_impl();
|
||||||
impl_
|
impl_.of_trait.as_ref().map(|ast_trait_ref| {
|
||||||
.of_trait
|
let selfty = tcx.type_of(def_id).instantiate_identity();
|
||||||
.as_ref()
|
|
||||||
.map(|hir_trait_ref| {
|
|
||||||
let self_ty = tcx.type_of(def_id).instantiate_identity();
|
|
||||||
|
|
||||||
let trait_ref = if let Some(ErrorGuaranteed { .. }) = check_impl_constness(
|
check_impl_constness(tcx, tcx.is_const_trait_impl_raw(def_id.to_def_id()), ast_trait_ref);
|
||||||
tcx,
|
|
||||||
tcx.is_const_trait_impl_raw(def_id.to_def_id()),
|
let trait_ref = icx.lowerer().lower_impl_trait_ref(ast_trait_ref, selfty);
|
||||||
hir_trait_ref,
|
|
||||||
) {
|
ty::ImplTraitHeader {
|
||||||
// we have a const impl, but for a trait without `#[const_trait]`, so
|
trait_ref: ty::EarlyBinder::bind(trait_ref),
|
||||||
// without the host param. If we continue with the HIR trait ref, we get
|
safety: impl_.safety,
|
||||||
// ICEs for generic arg count mismatch. We do a little HIR editing to
|
polarity: polarity_of_impl(tcx, def_id, impl_, item.span),
|
||||||
// make HIR ty lowering happy.
|
}
|
||||||
let mut path_segments = hir_trait_ref.path.segments.to_vec();
|
})
|
||||||
let last_segment = path_segments.len() - 1;
|
|
||||||
let mut args = *path_segments[last_segment].args();
|
|
||||||
let last_arg = args.args.len() - 1;
|
|
||||||
assert!(matches!(args.args[last_arg], hir::GenericArg::Const(anon_const) if anon_const.is_desugared_from_effects));
|
|
||||||
args.args = &args.args[..args.args.len() - 1];
|
|
||||||
path_segments[last_segment].args = Some(tcx.hir_arena.alloc(args));
|
|
||||||
let path = hir::Path {
|
|
||||||
span: hir_trait_ref.path.span,
|
|
||||||
res: hir_trait_ref.path.res,
|
|
||||||
segments: tcx.hir_arena.alloc_slice(&path_segments),
|
|
||||||
};
|
|
||||||
let trait_ref = tcx.hir_arena.alloc(hir::TraitRef { path: tcx.hir_arena.alloc(path), hir_ref_id: hir_trait_ref.hir_ref_id });
|
|
||||||
icx.lowerer().lower_impl_trait_ref(trait_ref, self_ty)
|
|
||||||
} else {
|
|
||||||
icx.lowerer().lower_impl_trait_ref(hir_trait_ref, self_ty)
|
|
||||||
};
|
|
||||||
ty::ImplTraitHeader {
|
|
||||||
trait_ref: ty::EarlyBinder::bind(trait_ref),
|
|
||||||
safety: impl_.safety,
|
|
||||||
polarity: polarity_of_impl(tcx, def_id, impl_, item.span)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_impl_constness(
|
fn check_impl_constness(
|
||||||
|
|
|
@ -354,7 +354,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
||||||
kind,
|
kind,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
GenericParamKind::Const { ty: _, default, is_host_effect } => {
|
GenericParamKind::Const { ty: _, default, is_host_effect, synthetic } => {
|
||||||
if !matches!(allow_defaults, Defaults::Allowed)
|
if !matches!(allow_defaults, Defaults::Allowed)
|
||||||
&& default.is_some()
|
&& default.is_some()
|
||||||
// `host` effect params are allowed to have defaults.
|
// `host` effect params are allowed to have defaults.
|
||||||
|
@ -388,6 +388,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
||||||
kind: ty::GenericParamDefKind::Const {
|
kind: ty::GenericParamDefKind::Const {
|
||||||
has_default: default.is_some(),
|
has_default: default.is_some(),
|
||||||
is_host_effect,
|
is_host_effect,
|
||||||
|
synthetic,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -541,7 +542,8 @@ struct AnonConstInParamTyDetector {
|
||||||
|
|
||||||
impl<'v> Visitor<'v> for AnonConstInParamTyDetector {
|
impl<'v> Visitor<'v> for AnonConstInParamTyDetector {
|
||||||
fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) {
|
fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) {
|
||||||
if let GenericParamKind::Const { ty, default: _, is_host_effect: _ } = p.kind {
|
if let GenericParamKind::Const { ty, default: _, is_host_effect: _, synthetic: _ } = p.kind
|
||||||
|
{
|
||||||
let prev = self.in_param_ty;
|
let prev = self.in_param_ty;
|
||||||
self.in_param_ty = true;
|
self.in_param_ty = true;
|
||||||
self.visit_ty(ty);
|
self.visit_ty(ty);
|
||||||
|
|
|
@ -8,6 +8,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFold
|
||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_span::def_id::{DefId, LocalDefId};
|
use rustc_span::def_id::{DefId, LocalDefId};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
use rustc_type_ir::Upcast;
|
||||||
|
|
||||||
/// For associated types we include both bounds written on the type
|
/// For associated types we include both bounds written on the type
|
||||||
/// (`type X: Trait`) and predicates from the trait: `where Self::X: Trait`.
|
/// (`type X: Trait`) and predicates from the trait: `where Self::X: Trait`.
|
||||||
|
@ -46,7 +47,7 @@ fn associated_type_bounds<'tcx>(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let all_bounds = tcx.arena.alloc_from_iter(bounds.clauses().chain(bounds_from_parent));
|
let all_bounds = tcx.arena.alloc_from_iter(bounds.clauses(tcx).chain(bounds_from_parent));
|
||||||
debug!(
|
debug!(
|
||||||
"associated_type_bounds({}) = {:?}",
|
"associated_type_bounds({}) = {:?}",
|
||||||
tcx.def_path_str(assoc_item_def_id.to_def_id()),
|
tcx.def_path_str(assoc_item_def_id.to_def_id()),
|
||||||
|
@ -75,7 +76,7 @@ fn opaque_type_bounds<'tcx>(
|
||||||
icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span);
|
icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span);
|
||||||
debug!(?bounds);
|
debug!(?bounds);
|
||||||
|
|
||||||
tcx.arena.alloc_from_iter(bounds.clauses())
|
tcx.arena.alloc_from_iter(bounds.clauses(tcx))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,6 +125,32 @@ pub(super) fn explicit_item_bounds_with_filter(
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if tcx.is_effects_desugared_assoc_ty(def_id.to_def_id()) {
|
||||||
|
let mut predicates = Vec::new();
|
||||||
|
|
||||||
|
let parent = tcx.local_parent(def_id);
|
||||||
|
|
||||||
|
let preds = tcx.explicit_predicates_of(parent);
|
||||||
|
|
||||||
|
if let ty::AssocItemContainer::TraitContainer = tcx.associated_item(def_id).container {
|
||||||
|
// for traits, emit `type Effects: TyCompat<<(T1::Effects, ..) as Min>::Output>`
|
||||||
|
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::EffectsIntersectionOutput, Some(span));
|
||||||
|
let proj = Ty::new_projection(tcx, assoc, [tup]);
|
||||||
|
let self_proj = Ty::new_projection(
|
||||||
|
tcx,
|
||||||
|
def_id.to_def_id(),
|
||||||
|
ty::GenericArgs::identity_for_item(tcx, def_id),
|
||||||
|
);
|
||||||
|
let trait_ = tcx.require_lang_item(hir::LangItem::EffectsTyCompat, Some(span));
|
||||||
|
let trait_ref = ty::TraitRef::new(tcx, trait_, [self_proj, proj]);
|
||||||
|
predicates.push((ty::Binder::dummy(trait_ref).upcast(tcx), span));
|
||||||
|
}
|
||||||
|
return ty::EarlyBinder::bind(tcx.arena.alloc_from_iter(predicates));
|
||||||
|
}
|
||||||
|
|
||||||
let bounds = match tcx.hir_node_by_def_id(def_id) {
|
let bounds = match tcx.hir_node_by_def_id(def_id) {
|
||||||
hir::Node::TraitItem(hir::TraitItem {
|
hir::Node::TraitItem(hir::TraitItem {
|
||||||
kind: hir::TraitItemKind::Type(bounds, _),
|
kind: hir::TraitItemKind::Type(bounds, _),
|
||||||
|
|
|
@ -57,6 +57,7 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic
|
||||||
#[instrument(level = "trace", skip(tcx), ret)]
|
#[instrument(level = "trace", skip(tcx), ret)]
|
||||||
fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::GenericPredicates<'_> {
|
fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::GenericPredicates<'_> {
|
||||||
use rustc_hir::*;
|
use rustc_hir::*;
|
||||||
|
use rustc_middle::ty::Ty;
|
||||||
|
|
||||||
match tcx.opt_rpitit_info(def_id.to_def_id()) {
|
match tcx.opt_rpitit_info(def_id.to_def_id()) {
|
||||||
Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) => {
|
Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) => {
|
||||||
|
@ -84,6 +85,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||||
return ty::GenericPredicates {
|
return ty::GenericPredicates {
|
||||||
parent: Some(tcx.parent(def_id.to_def_id())),
|
parent: Some(tcx.parent(def_id.to_def_id())),
|
||||||
predicates: tcx.arena.alloc_from_iter(predicates),
|
predicates: tcx.arena.alloc_from_iter(predicates),
|
||||||
|
effects_min_tys: ty::List::empty(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,6 +107,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||||
return ty::GenericPredicates {
|
return ty::GenericPredicates {
|
||||||
parent: Some(impl_def_id),
|
parent: Some(impl_def_id),
|
||||||
predicates: tcx.arena.alloc_from_iter(impl_predicates),
|
predicates: tcx.arena.alloc_from_iter(impl_predicates),
|
||||||
|
effects_min_tys: ty::List::empty(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,6 +127,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||||
// We use an `IndexSet` to preserve order of insertion.
|
// We use an `IndexSet` to preserve order of insertion.
|
||||||
// Preserving the order of insertion is important here so as not to break UI tests.
|
// Preserving the order of insertion is important here so as not to break UI tests.
|
||||||
let mut predicates: FxIndexSet<(ty::Clause<'_>, Span)> = FxIndexSet::default();
|
let mut predicates: FxIndexSet<(ty::Clause<'_>, Span)> = FxIndexSet::default();
|
||||||
|
let mut effects_min_tys = Vec::new();
|
||||||
|
|
||||||
let hir_generics = node.generics().unwrap_or(NO_GENERICS);
|
let hir_generics = node.generics().unwrap_or(NO_GENERICS);
|
||||||
if let Node::Item(item) = node {
|
if let Node::Item(item) = node {
|
||||||
|
@ -150,11 +154,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||||
// on a trait we must also consider the bounds that follow the trait's name,
|
// on a trait we must also consider the bounds that follow the trait's name,
|
||||||
// like `trait Foo: A + B + C`.
|
// like `trait Foo: A + B + C`.
|
||||||
if let Some(self_bounds) = is_trait {
|
if let Some(self_bounds) = is_trait {
|
||||||
predicates.extend(
|
let bounds = icx.lowerer().lower_mono_bounds(
|
||||||
icx.lowerer()
|
tcx.types.self_param,
|
||||||
.lower_mono_bounds(tcx.types.self_param, self_bounds, PredicateFilter::All)
|
self_bounds,
|
||||||
.clauses(),
|
PredicateFilter::All,
|
||||||
);
|
);
|
||||||
|
predicates.extend(bounds.clauses(tcx));
|
||||||
|
effects_min_tys.extend(bounds.effects_min_tys());
|
||||||
}
|
}
|
||||||
|
|
||||||
// In default impls, we can assume that the self type implements
|
// In default impls, we can assume that the self type implements
|
||||||
|
@ -187,7 +193,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||||
param.span,
|
param.span,
|
||||||
);
|
);
|
||||||
trace!(?bounds);
|
trace!(?bounds);
|
||||||
predicates.extend(bounds.clauses());
|
predicates.extend(bounds.clauses(tcx));
|
||||||
trace!(?predicates);
|
trace!(?predicates);
|
||||||
}
|
}
|
||||||
hir::GenericParamKind::Const { .. } => {
|
hir::GenericParamKind::Const { .. } => {
|
||||||
|
@ -238,7 +244,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||||
bound_vars,
|
bound_vars,
|
||||||
OnlySelfBounds(false),
|
OnlySelfBounds(false),
|
||||||
);
|
);
|
||||||
predicates.extend(bounds.clauses());
|
predicates.extend(bounds.clauses(tcx));
|
||||||
|
effects_min_tys.extend(bounds.effects_min_tys());
|
||||||
}
|
}
|
||||||
|
|
||||||
hir::WherePredicate::RegionPredicate(region_pred) => {
|
hir::WherePredicate::RegionPredicate(region_pred) => {
|
||||||
|
@ -297,7 +304,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||||
// and the duplicated parameter, to ensure that they do not get out of sync.
|
// and the duplicated parameter, to ensure that they do not get out of sync.
|
||||||
if let Node::Item(&Item { kind: ItemKind::OpaqueTy(..), .. }) = node {
|
if let Node::Item(&Item { kind: ItemKind::OpaqueTy(..), .. }) = node {
|
||||||
let opaque_ty_node = tcx.parent_hir_node(hir_id);
|
let opaque_ty_node = tcx.parent_hir_node(hir_id);
|
||||||
let Node::Ty(&Ty { kind: TyKind::OpaqueDef(_, lifetimes, _), .. }) = opaque_ty_node else {
|
let Node::Ty(&hir::Ty { kind: TyKind::OpaqueDef(_, lifetimes, _), .. }) = opaque_ty_node
|
||||||
|
else {
|
||||||
bug!("unexpected {opaque_ty_node:?}")
|
bug!("unexpected {opaque_ty_node:?}")
|
||||||
};
|
};
|
||||||
debug!(?lifetimes);
|
debug!(?lifetimes);
|
||||||
|
@ -306,9 +314,30 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||||
debug!(?predicates);
|
debug!(?predicates);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add `Self::Effects: Compat<HOST>` to ensure non-const impls don't get called
|
||||||
|
// in const contexts.
|
||||||
|
if let Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(..), .. }) = node
|
||||||
|
&& let Some(host_effect_index) = generics.host_effect_index
|
||||||
|
{
|
||||||
|
let parent = generics.parent.unwrap();
|
||||||
|
let Some(assoc_def_id) = tcx.associated_type_for_effects(parent) else {
|
||||||
|
bug!("associated_type_for_effects returned None when there is host effect in generics");
|
||||||
|
};
|
||||||
|
let effects =
|
||||||
|
Ty::new_projection(tcx, assoc_def_id, ty::GenericArgs::identity_for_item(tcx, parent));
|
||||||
|
let param = generics.param_at(host_effect_index, tcx);
|
||||||
|
let span = tcx.def_span(param.def_id);
|
||||||
|
let host = ty::Const::new_param(tcx, ty::ParamConst::for_def(param));
|
||||||
|
let compat = tcx.require_lang_item(LangItem::EffectsCompat, Some(span));
|
||||||
|
let trait_ref =
|
||||||
|
ty::TraitRef::new(tcx, compat, [ty::GenericArg::from(effects), host.into()]);
|
||||||
|
predicates.push((ty::Binder::dummy(trait_ref).upcast(tcx), span));
|
||||||
|
}
|
||||||
|
|
||||||
ty::GenericPredicates {
|
ty::GenericPredicates {
|
||||||
parent: generics.parent,
|
parent: generics.parent,
|
||||||
predicates: tcx.arena.alloc_from_iter(predicates),
|
predicates: tcx.arena.alloc_from_iter(predicates),
|
||||||
|
effects_min_tys: tcx.mk_type_list(&effects_min_tys),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,6 +488,7 @@ pub(super) fn explicit_predicates_of<'tcx>(
|
||||||
ty::GenericPredicates {
|
ty::GenericPredicates {
|
||||||
parent: predicates_and_bounds.parent,
|
parent: predicates_and_bounds.parent,
|
||||||
predicates: tcx.arena.alloc_slice(&predicates),
|
predicates: tcx.arena.alloc_slice(&predicates),
|
||||||
|
effects_min_tys: predicates_and_bounds.effects_min_tys,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -510,6 +540,7 @@ pub(super) fn explicit_predicates_of<'tcx>(
|
||||||
return GenericPredicates {
|
return GenericPredicates {
|
||||||
parent: parent_preds.parent,
|
parent: parent_preds.parent,
|
||||||
predicates: { tcx.arena.alloc_from_iter(filtered_predicates) },
|
predicates: { tcx.arena.alloc_from_iter(filtered_predicates) },
|
||||||
|
effects_min_tys: parent_preds.effects_min_tys,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
gather_explicit_predicates_of(tcx, def_id)
|
gather_explicit_predicates_of(tcx, def_id)
|
||||||
|
@ -587,7 +618,7 @@ pub(super) fn implied_predicates_with_filter(
|
||||||
|
|
||||||
// Combine the two lists to form the complete set of superbounds:
|
// Combine the two lists to form the complete set of superbounds:
|
||||||
let implied_bounds =
|
let implied_bounds =
|
||||||
&*tcx.arena.alloc_from_iter(superbounds.clauses().chain(where_bounds_that_match));
|
&*tcx.arena.alloc_from_iter(superbounds.clauses(tcx).chain(where_bounds_that_match));
|
||||||
debug!(?implied_bounds);
|
debug!(?implied_bounds);
|
||||||
|
|
||||||
// Now require that immediate supertraits are lowered, which will, in
|
// Now require that immediate supertraits are lowered, which will, in
|
||||||
|
@ -618,7 +649,11 @@ pub(super) fn implied_predicates_with_filter(
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::GenericPredicates { parent: None, predicates: implied_bounds }
|
ty::GenericPredicates {
|
||||||
|
parent: None,
|
||||||
|
predicates: implied_bounds,
|
||||||
|
effects_min_tys: ty::List::empty(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the predicates defined on `item_def_id` of the form
|
/// Returns the predicates defined on `item_def_id` of the form
|
||||||
|
@ -744,7 +779,7 @@ impl<'tcx> ItemCtxt<'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bounds.clauses().collect()
|
bounds.clauses(self.tcx).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self))]
|
#[instrument(level = "trace", skip(self))]
|
||||||
|
|
|
@ -951,7 +951,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
||||||
self.visit_ty(ty);
|
self.visit_ty(ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GenericParamKind::Const { ty, default, is_host_effect: _ } => {
|
GenericParamKind::Const { ty, default, .. } => {
|
||||||
self.visit_ty(ty);
|
self.visit_ty(ty);
|
||||||
if let Some(default) = default {
|
if let Some(default) = default {
|
||||||
self.visit_body(self.tcx.hir().body(default.body));
|
self.visit_body(self.tcx.hir().body(default.body));
|
||||||
|
|
|
@ -256,6 +256,7 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
|
||||||
| GenericParamDefKind::Lifetime,
|
| GenericParamDefKind::Lifetime,
|
||||||
_,
|
_,
|
||||||
) => {
|
) => {
|
||||||
|
// FIXME(effects): this should be removed
|
||||||
// SPECIAL CASE FOR DESUGARED EFFECT PARAMS
|
// SPECIAL CASE FOR DESUGARED EFFECT PARAMS
|
||||||
// This comes from the following example:
|
// This comes from the following example:
|
||||||
//
|
//
|
||||||
|
@ -445,7 +446,7 @@ pub(crate) fn check_generic_arg_count(
|
||||||
.own_params
|
.own_params
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|param| {
|
.filter(|param| {
|
||||||
matches!(param.kind, ty::GenericParamDefKind::Const { is_host_effect: true, .. })
|
matches!(param.kind, ty::GenericParamDefKind::Const { synthetic: true, .. })
|
||||||
})
|
})
|
||||||
.count();
|
.count();
|
||||||
let named_const_param_count = param_counts.consts - synth_const_param_count;
|
let named_const_param_count = param_counts.consts - synth_const_param_count;
|
||||||
|
|
|
@ -698,7 +698,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
);
|
);
|
||||||
|
|
||||||
debug!(?poly_trait_ref);
|
debug!(?poly_trait_ref);
|
||||||
bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity);
|
bounds.push_trait_bound(
|
||||||
|
tcx,
|
||||||
|
self.item_def_id().to_def_id(),
|
||||||
|
poly_trait_ref,
|
||||||
|
span,
|
||||||
|
polarity,
|
||||||
|
constness,
|
||||||
|
);
|
||||||
|
|
||||||
let mut dup_constraints = FxIndexMap::default();
|
let mut dup_constraints = FxIndexMap::default();
|
||||||
for constraint in trait_segment.args().constraints {
|
for constraint in trait_segment.args().constraints {
|
||||||
|
|
|
@ -59,7 +59,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
|
|
||||||
let mut trait_bounds = vec![];
|
let mut trait_bounds = vec![];
|
||||||
let mut projection_bounds = vec![];
|
let mut projection_bounds = vec![];
|
||||||
for (pred, span) in bounds.clauses() {
|
for (pred, span) in bounds.clauses(tcx) {
|
||||||
let bound_pred = pred.kind();
|
let bound_pred = pred.kind();
|
||||||
match bound_pred.skip_binder() {
|
match bound_pred.skip_binder() {
|
||||||
ty::ClauseKind::Trait(trait_pred) => {
|
ty::ClauseKind::Trait(trait_pred) => {
|
||||||
|
@ -133,7 +133,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||||
tcx.associated_items(pred.def_id())
|
tcx.associated_items(pred.def_id())
|
||||||
.in_definition_order()
|
.in_definition_order()
|
||||||
.filter(|item| item.kind == ty::AssocKind::Type)
|
.filter(|item| item.kind == ty::AssocKind::Type)
|
||||||
.filter(|item| !item.is_impl_trait_in_trait())
|
.filter(|item| {
|
||||||
|
!item.is_impl_trait_in_trait() && !item.is_effects_desugaring
|
||||||
|
})
|
||||||
.map(|item| item.def_id),
|
.map(|item| item.def_id),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -585,6 +585,7 @@ impl<'a> State<'a> {
|
||||||
self.print_struct(struct_def, generics, item.ident.name, item.span, true);
|
self.print_struct(struct_def, generics, item.ident.name, item.span, true);
|
||||||
}
|
}
|
||||||
hir::ItemKind::Impl(&hir::Impl {
|
hir::ItemKind::Impl(&hir::Impl {
|
||||||
|
constness,
|
||||||
safety,
|
safety,
|
||||||
polarity,
|
polarity,
|
||||||
defaultness,
|
defaultness,
|
||||||
|
@ -599,6 +600,10 @@ impl<'a> State<'a> {
|
||||||
self.print_safety(safety);
|
self.print_safety(safety);
|
||||||
self.word_nbsp("impl");
|
self.word_nbsp("impl");
|
||||||
|
|
||||||
|
if let hir::Constness::Const = constness {
|
||||||
|
self.word_nbsp("const");
|
||||||
|
}
|
||||||
|
|
||||||
if !generics.params.is_empty() {
|
if !generics.params.is_empty() {
|
||||||
self.print_generic_params(generics.params);
|
self.print_generic_params(generics.params);
|
||||||
self.space();
|
self.space();
|
||||||
|
@ -2144,7 +2149,7 @@ impl<'a> State<'a> {
|
||||||
self.print_type(default);
|
self.print_type(default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GenericParamKind::Const { ty, ref default, is_host_effect: _ } => {
|
GenericParamKind::Const { ty, ref default, is_host_effect: _, synthetic: _ } => {
|
||||||
self.word_space(":");
|
self.word_space(":");
|
||||||
self.print_type(ty);
|
self.print_type(ty);
|
||||||
if let Some(default) = default {
|
if let Some(default) = default {
|
||||||
|
|
|
@ -1304,7 +1304,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
self.fcx.ty_infer(Some(param), inf.span).into()
|
self.fcx.ty_infer(Some(param), inf.span).into()
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
&GenericParamDefKind::Const { has_default, is_host_effect },
|
&GenericParamDefKind::Const { has_default, is_host_effect, .. },
|
||||||
GenericArg::Infer(inf),
|
GenericArg::Infer(inf),
|
||||||
) => {
|
) => {
|
||||||
if has_default && is_host_effect {
|
if has_default && is_host_effect {
|
||||||
|
@ -1346,7 +1346,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
self.fcx.var_for_def(self.span, param)
|
self.fcx.var_for_def(self.span, param)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GenericParamDefKind::Const { has_default, is_host_effect } => {
|
GenericParamDefKind::Const { has_default, is_host_effect, .. } => {
|
||||||
if has_default {
|
if has_default {
|
||||||
// N.B. this is a bit of a hack. `infer_args` is passed depending on
|
// N.B. this is a bit of a hack. `infer_args` is passed depending on
|
||||||
// whether the user has provided generic args. E.g. for `Vec::new`
|
// whether the user has provided generic args. E.g. for `Vec::new`
|
||||||
|
|
|
@ -274,6 +274,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
effects_min_tys: ty::List::empty(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ use rustc_middle::ty::{self, GenericParamDefKind, Ty, TypeVisitableExt};
|
||||||
use rustc_middle::ty::{GenericArgs, GenericArgsRef};
|
use rustc_middle::ty::{GenericArgs, GenericArgsRef};
|
||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_span::symbol::Ident;
|
use rustc_span::symbol::Ident;
|
||||||
use rustc_span::Span;
|
use rustc_span::{sym, Span};
|
||||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
||||||
use rustc_trait_selection::traits::{self, NormalizeExt};
|
use rustc_trait_selection::traits::{self, NormalizeExt};
|
||||||
|
|
||||||
|
@ -356,6 +356,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
|
) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
|
||||||
let (obligation, args) =
|
let (obligation, args) =
|
||||||
self.obligation_for_method(cause, trait_def_id, self_ty, opt_input_types);
|
self.obligation_for_method(cause, trait_def_id, self_ty, opt_input_types);
|
||||||
|
// FIXME(effects) find a better way to do this
|
||||||
|
// Operators don't have generic methods, but making them `#[const_trait]` gives them
|
||||||
|
// `const host: bool`.
|
||||||
|
let args = if self.tcx.has_attr(trait_def_id, sym::const_trait) {
|
||||||
|
self.tcx.mk_args_from_iter(
|
||||||
|
args.iter()
|
||||||
|
.chain([self.tcx.expected_host_effect_param_for_body(self.body_id).into()]),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
args
|
||||||
|
};
|
||||||
self.construct_obligation_for_trait(m_name, trait_def_id, obligation, args)
|
self.construct_obligation_for_trait(m_name, trait_def_id, obligation, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,6 +404,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
debug!("lookup_in_trait_adjusted: method_item={:?}", method_item);
|
debug!("lookup_in_trait_adjusted: method_item={:?}", method_item);
|
||||||
let mut obligations = vec![];
|
let mut obligations = vec![];
|
||||||
|
|
||||||
|
// FIXME(effects): revisit when binops get `#[const_trait]`
|
||||||
|
|
||||||
// Instantiate late-bound regions and instantiate the trait
|
// Instantiate late-bound regions and instantiate the trait
|
||||||
// parameters into the method type to get the actual method type.
|
// parameters into the method type to get the actual method type.
|
||||||
//
|
//
|
||||||
|
|
|
@ -1279,6 +1279,7 @@ impl<'tcx> Pick<'tcx> {
|
||||||
trait_item_def_id: _,
|
trait_item_def_id: _,
|
||||||
fn_has_self_parameter: _,
|
fn_has_self_parameter: _,
|
||||||
opt_rpitit_info: _,
|
opt_rpitit_info: _,
|
||||||
|
is_effects_desugaring: _,
|
||||||
},
|
},
|
||||||
kind: _,
|
kind: _,
|
||||||
import_ids: _,
|
import_ids: _,
|
||||||
|
|
|
@ -1348,7 +1348,9 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_associated_item(self, id: DefIndex, sess: &'a Session) -> ty::AssocItem {
|
fn get_associated_item(self, id: DefIndex, sess: &'a Session) -> ty::AssocItem {
|
||||||
let name = if self.root.tables.opt_rpitit_info.get(self, id).is_some() {
|
let name = if self.root.tables.opt_rpitit_info.get(self, id).is_some()
|
||||||
|
|| self.root.tables.is_effects_desugaring.get(self, id)
|
||||||
|
{
|
||||||
kw::Empty
|
kw::Empty
|
||||||
} else {
|
} else {
|
||||||
self.item_name(id)
|
self.item_name(id)
|
||||||
|
@ -1371,6 +1373,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
|
||||||
container,
|
container,
|
||||||
fn_has_self_parameter: has_self,
|
fn_has_self_parameter: has_self,
|
||||||
opt_rpitit_info,
|
opt_rpitit_info,
|
||||||
|
is_effects_desugaring: self.root.tables.is_effects_desugaring.get(self, id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -279,6 +279,9 @@ provide! { tcx, def_id, other, cdata,
|
||||||
.process_decoded(tcx, || panic!("{def_id:?} does not have trait_impl_trait_tys")))
|
.process_decoded(tcx, || panic!("{def_id:?} does not have trait_impl_trait_tys")))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
associated_type_for_effects => {
|
||||||
|
table
|
||||||
|
}
|
||||||
associated_types_for_impl_traits_in_associated_fn => { table_defaulted_array }
|
associated_types_for_impl_traits_in_associated_fn => { table_defaulted_array }
|
||||||
|
|
||||||
visibility => { cdata.get_visibility(def_id.index) }
|
visibility => { cdata.get_visibility(def_id.index) }
|
||||||
|
|
|
@ -1454,6 +1454,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
for &def_id in associated_item_def_ids {
|
for &def_id in associated_item_def_ids {
|
||||||
self.encode_info_for_assoc_item(def_id);
|
self.encode_info_for_assoc_item(def_id);
|
||||||
}
|
}
|
||||||
|
if let Some(assoc_def_id) = self.tcx.associated_type_for_effects(def_id) {
|
||||||
|
record!(self.tables.associated_type_for_effects[def_id] <- assoc_def_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if def_kind == DefKind::Closure
|
if def_kind == DefKind::Closure
|
||||||
&& let Some(coroutine_kind) = self.tcx.coroutine_kind(def_id)
|
&& let Some(coroutine_kind) = self.tcx.coroutine_kind(def_id)
|
||||||
|
@ -1634,6 +1637,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if item.is_effects_desugaring {
|
||||||
|
self.tables.is_effects_desugaring.set(def_id.index, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_mir(&mut self) {
|
fn encode_mir(&mut self) {
|
||||||
|
|
|
@ -391,7 +391,9 @@ define_tables! {
|
||||||
inferred_outlives_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
|
inferred_outlives_of: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>,
|
||||||
inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
|
inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
|
||||||
associated_types_for_impl_traits_in_associated_fn: Table<DefIndex, LazyArray<DefId>>,
|
associated_types_for_impl_traits_in_associated_fn: Table<DefIndex, LazyArray<DefId>>,
|
||||||
|
associated_type_for_effects: Table<DefIndex, Option<LazyValue<DefId>>>,
|
||||||
opt_rpitit_info: Table<DefIndex, Option<LazyValue<ty::ImplTraitInTraitData>>>,
|
opt_rpitit_info: Table<DefIndex, Option<LazyValue<ty::ImplTraitInTraitData>>>,
|
||||||
|
is_effects_desugaring: Table<DefIndex, bool>,
|
||||||
unused_generic_params: Table<DefIndex, UnusedGenericParams>,
|
unused_generic_params: Table<DefIndex, UnusedGenericParams>,
|
||||||
// Reexported names are not associated with individual `DefId`s,
|
// Reexported names are not associated with individual `DefId`s,
|
||||||
// e.g. a glob import can introduce a lot of names, all with the same `DefId`.
|
// e.g. a glob import can introduce a lot of names, all with the same `DefId`.
|
||||||
|
|
|
@ -368,6 +368,7 @@ rustc_queries! {
|
||||||
desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) }
|
desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) }
|
||||||
cache_on_disk_if { key.is_local() }
|
cache_on_disk_if { key.is_local() }
|
||||||
separate_provide_extern
|
separate_provide_extern
|
||||||
|
feedable
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The set of item bounds (see [`TyCtxt::explicit_item_bounds`]) that
|
/// The set of item bounds (see [`TyCtxt::explicit_item_bounds`]) that
|
||||||
|
@ -378,6 +379,7 @@ rustc_queries! {
|
||||||
desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) }
|
desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) }
|
||||||
cache_on_disk_if { key.is_local() }
|
cache_on_disk_if { key.is_local() }
|
||||||
separate_provide_extern
|
separate_provide_extern
|
||||||
|
feedable
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Elaborated version of the predicates from `explicit_item_bounds`.
|
/// Elaborated version of the predicates from `explicit_item_bounds`.
|
||||||
|
@ -853,6 +855,12 @@ rustc_queries! {
|
||||||
separate_provide_extern
|
separate_provide_extern
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query associated_type_for_effects(def_id: DefId) -> Option<DefId> {
|
||||||
|
desc { |tcx| "creating associated items for effects in `{}`", tcx.def_path_str(def_id) }
|
||||||
|
cache_on_disk_if { def_id.is_local() }
|
||||||
|
separate_provide_extern
|
||||||
|
}
|
||||||
|
|
||||||
/// Given an impl trait in trait `opaque_ty_def_id`, create and return the corresponding
|
/// Given an impl trait in trait `opaque_ty_def_id`, create and return the corresponding
|
||||||
/// associated item.
|
/// associated item.
|
||||||
query associated_type_for_impl_trait_in_trait(opaque_ty_def_id: LocalDefId) -> LocalDefId {
|
query associated_type_for_impl_trait_in_trait(opaque_ty_def_id: LocalDefId) -> LocalDefId {
|
||||||
|
|
|
@ -34,6 +34,8 @@ pub struct AssocItem {
|
||||||
/// return-position `impl Trait` in trait desugaring. The `ImplTraitInTraitData`
|
/// return-position `impl Trait` in trait desugaring. The `ImplTraitInTraitData`
|
||||||
/// provides additional information about its source.
|
/// provides additional information about its source.
|
||||||
pub opt_rpitit_info: Option<ty::ImplTraitInTraitData>,
|
pub opt_rpitit_info: Option<ty::ImplTraitInTraitData>,
|
||||||
|
|
||||||
|
pub is_effects_desugaring: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AssocItem {
|
impl AssocItem {
|
||||||
|
|
|
@ -601,6 +601,11 @@ fn trait_lang_item_to_lang_item(lang_item: TraitSolverLangItem) -> LangItem {
|
||||||
TraitSolverLangItem::Destruct => LangItem::Destruct,
|
TraitSolverLangItem::Destruct => LangItem::Destruct,
|
||||||
TraitSolverLangItem::DiscriminantKind => LangItem::DiscriminantKind,
|
TraitSolverLangItem::DiscriminantKind => LangItem::DiscriminantKind,
|
||||||
TraitSolverLangItem::DynMetadata => LangItem::DynMetadata,
|
TraitSolverLangItem::DynMetadata => LangItem::DynMetadata,
|
||||||
|
TraitSolverLangItem::EffectsMaybe => LangItem::EffectsMaybe,
|
||||||
|
TraitSolverLangItem::EffectsIntersection => LangItem::EffectsIntersection,
|
||||||
|
TraitSolverLangItem::EffectsIntersectionOutput => LangItem::EffectsIntersectionOutput,
|
||||||
|
TraitSolverLangItem::EffectsNoRuntime => LangItem::EffectsNoRuntime,
|
||||||
|
TraitSolverLangItem::EffectsRuntime => LangItem::EffectsRuntime,
|
||||||
TraitSolverLangItem::FnPtrTrait => LangItem::FnPtrTrait,
|
TraitSolverLangItem::FnPtrTrait => LangItem::FnPtrTrait,
|
||||||
TraitSolverLangItem::FusedIterator => LangItem::FusedIterator,
|
TraitSolverLangItem::FusedIterator => LangItem::FusedIterator,
|
||||||
TraitSolverLangItem::Future => LangItem::Future,
|
TraitSolverLangItem::Future => LangItem::Future,
|
||||||
|
@ -3098,9 +3103,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
matches!(
|
matches!(
|
||||||
node,
|
node,
|
||||||
hir::Node::Item(hir::Item {
|
hir::Node::Item(hir::Item {
|
||||||
kind: hir::ItemKind::Impl(hir::Impl { generics, .. }),
|
kind: hir::ItemKind::Impl(hir::Impl { constness, .. }),
|
||||||
..
|
..
|
||||||
}) if generics.params.iter().any(|p| matches!(p.kind, hir::GenericParamKind::Const { is_host_effect: true, .. }))
|
}) if matches!(constness, hir::Constness::Const)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ use super::{Clause, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt};
|
||||||
pub enum GenericParamDefKind {
|
pub enum GenericParamDefKind {
|
||||||
Lifetime,
|
Lifetime,
|
||||||
Type { has_default: bool, synthetic: bool },
|
Type { has_default: bool, synthetic: bool },
|
||||||
Const { has_default: bool, is_host_effect: bool },
|
Const { has_default: bool, is_host_effect: bool, synthetic: bool },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GenericParamDefKind {
|
impl GenericParamDefKind {
|
||||||
|
@ -371,6 +371,7 @@ impl<'tcx> Generics {
|
||||||
pub struct GenericPredicates<'tcx> {
|
pub struct GenericPredicates<'tcx> {
|
||||||
pub parent: Option<DefId>,
|
pub parent: Option<DefId>,
|
||||||
pub predicates: &'tcx [(Clause<'tcx>, Span)],
|
pub predicates: &'tcx [(Clause<'tcx>, Span)],
|
||||||
|
pub effects_min_tys: &'tcx ty::List<Ty<'tcx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> GenericPredicates<'tcx> {
|
impl<'tcx> GenericPredicates<'tcx> {
|
||||||
|
|
|
@ -1608,7 +1608,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If the def-id is an associated type that was desugared from a
|
/// If the `def_id` is an associated type that was desugared from a
|
||||||
/// return-position `impl Trait` from a trait, then provide the source info
|
/// return-position `impl Trait` from a trait, then provide the source info
|
||||||
/// about where that RPITIT came from.
|
/// about where that RPITIT came from.
|
||||||
pub fn opt_rpitit_info(self, def_id: DefId) -> Option<ImplTraitInTraitData> {
|
pub fn opt_rpitit_info(self, def_id: DefId) -> Option<ImplTraitInTraitData> {
|
||||||
|
@ -1619,6 +1619,16 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether the `def_id` is an associated type that was desugared from a
|
||||||
|
/// `#[const_trait]` or `impl_const`.
|
||||||
|
pub fn is_effects_desugared_assoc_ty(self, def_id: DefId) -> bool {
|
||||||
|
if let DefKind::AssocTy = self.def_kind(def_id) {
|
||||||
|
self.associated_item(def_id).is_effects_desugaring
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<FieldIdx> {
|
pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<FieldIdx> {
|
||||||
variant.fields.iter_enumerated().find_map(|(i, field)| {
|
variant.fields.iter_enumerated().find_map(|(i, field)| {
|
||||||
self.hygienic_eq(ident, field.ident(self), variant.def_id).then_some(i)
|
self.hygienic_eq(ident, field.ident(self), variant.def_id).then_some(i)
|
||||||
|
|
|
@ -269,6 +269,11 @@ where
|
||||||
ecx: &mut EvalCtxt<'_, D>,
|
ecx: &mut EvalCtxt<'_, D>,
|
||||||
goal: Goal<I, Self>,
|
goal: Goal<I, Self>,
|
||||||
) -> Vec<Candidate<I>>;
|
) -> Vec<Candidate<I>>;
|
||||||
|
|
||||||
|
fn consider_builtin_effects_intersection_candidate(
|
||||||
|
ecx: &mut EvalCtxt<'_, D>,
|
||||||
|
goal: Goal<I, Self>,
|
||||||
|
) -> Result<Candidate<I>, NoSolution>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D, I> EvalCtxt<'_, D>
|
impl<D, I> EvalCtxt<'_, D>
|
||||||
|
@ -420,6 +425,8 @@ where
|
||||||
G::consider_builtin_destruct_candidate(self, goal)
|
G::consider_builtin_destruct_candidate(self, goal)
|
||||||
} else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::TransmuteTrait) {
|
} else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::TransmuteTrait) {
|
||||||
G::consider_builtin_transmute_candidate(self, goal)
|
G::consider_builtin_transmute_candidate(self, goal)
|
||||||
|
} else if cx.is_lang_item(trait_def_id, TraitSolverLangItem::EffectsIntersection) {
|
||||||
|
G::consider_builtin_effects_intersection_candidate(self, goal)
|
||||||
} else {
|
} else {
|
||||||
Err(NoSolution)
|
Err(NoSolution)
|
||||||
};
|
};
|
||||||
|
|
|
@ -864,6 +864,68 @@ where
|
||||||
) -> Result<Candidate<I>, NoSolution> {
|
) -> Result<Candidate<I>, NoSolution> {
|
||||||
panic!("`BikeshedIntrinsicFrom` does not have an associated type: {:?}", goal)
|
panic!("`BikeshedIntrinsicFrom` does not have an associated type: {:?}", goal)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn consider_builtin_effects_intersection_candidate(
|
||||||
|
ecx: &mut EvalCtxt<'_, D>,
|
||||||
|
goal: Goal<I, Self>,
|
||||||
|
) -> Result<Candidate<I>, NoSolution> {
|
||||||
|
let ty::Tuple(types) = goal.predicate.self_ty().kind() else {
|
||||||
|
return Err(NoSolution);
|
||||||
|
};
|
||||||
|
|
||||||
|
let cx = ecx.cx();
|
||||||
|
|
||||||
|
let mut first_non_maybe = None;
|
||||||
|
let mut non_maybe_count = 0;
|
||||||
|
for ty in types.iter() {
|
||||||
|
if !matches!(ty::EffectKind::try_from_ty(cx, ty), Some(ty::EffectKind::Maybe)) {
|
||||||
|
first_non_maybe.get_or_insert(ty);
|
||||||
|
non_maybe_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match non_maybe_count {
|
||||||
|
0 => {
|
||||||
|
let ty = ty::EffectKind::Maybe.to_ty(cx);
|
||||||
|
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
|
||||||
|
ecx.instantiate_normalizes_to_term(goal, ty.into());
|
||||||
|
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
1 => {
|
||||||
|
let ty = first_non_maybe.unwrap();
|
||||||
|
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
|
||||||
|
ecx.instantiate_normalizes_to_term(goal, ty.into());
|
||||||
|
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
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::intersection(min, kind) else {
|
||||||
|
return Err(NoSolution);
|
||||||
|
};
|
||||||
|
|
||||||
|
min = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
let ty = min.to_ty(cx);
|
||||||
|
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
|
||||||
|
ecx.instantiate_normalizes_to_term(goal, ty.into());
|
||||||
|
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D, I> EvalCtxt<'_, D>
|
impl<D, I> EvalCtxt<'_, D>
|
||||||
|
|
|
@ -702,6 +702,47 @@ where
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn consider_builtin_effects_intersection_candidate(
|
||||||
|
ecx: &mut EvalCtxt<'_, D>,
|
||||||
|
goal: Goal<I, Self>,
|
||||||
|
) -> Result<Candidate<I>, NoSolution> {
|
||||||
|
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
|
||||||
|
return Err(NoSolution);
|
||||||
|
}
|
||||||
|
|
||||||
|
let ty::Tuple(types) = goal.predicate.self_ty().kind() else {
|
||||||
|
return Err(NoSolution);
|
||||||
|
};
|
||||||
|
|
||||||
|
let cx = ecx.cx();
|
||||||
|
let maybe_count = types
|
||||||
|
.iter()
|
||||||
|
.filter_map(|ty| ty::EffectKind::try_from_ty(cx, ty))
|
||||||
|
.filter(|&ty| ty == ty::EffectKind::Maybe)
|
||||||
|
.count();
|
||||||
|
|
||||||
|
// Don't do concrete type check unless there are more than one type that will influence the result.
|
||||||
|
// This would allow `(Maybe, T): Min` pass even if we know nothing about `T`.
|
||||||
|
if types.len() - maybe_count > 1 {
|
||||||
|
let mut min = ty::EffectKind::Maybe;
|
||||||
|
|
||||||
|
for ty in types.iter() {
|
||||||
|
let Some(kind) = ty::EffectKind::try_from_ty(ecx.cx(), ty) else {
|
||||||
|
return Err(NoSolution);
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(result) = ty::EffectKind::intersection(min, kind) else {
|
||||||
|
return Err(NoSolution);
|
||||||
|
};
|
||||||
|
|
||||||
|
min = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc)
|
||||||
|
.enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D, I> EvalCtxt<'_, D>
|
impl<D, I> EvalCtxt<'_, D>
|
||||||
|
|
|
@ -160,7 +160,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
|
||||||
fn predicates_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPredicates {
|
fn predicates_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPredicates {
|
||||||
let mut tables = self.0.borrow_mut();
|
let mut tables = self.0.borrow_mut();
|
||||||
let def_id = tables[def_id];
|
let def_id = tables[def_id];
|
||||||
let GenericPredicates { parent, predicates } = tables.tcx.predicates_of(def_id);
|
let GenericPredicates { parent, predicates, effects_min_tys: _ } =
|
||||||
|
tables.tcx.predicates_of(def_id);
|
||||||
stable_mir::ty::GenericPredicates {
|
stable_mir::ty::GenericPredicates {
|
||||||
parent: parent.map(|did| tables.trait_def(did)),
|
parent: parent.map(|did| tables.trait_def(did)),
|
||||||
predicates: predicates
|
predicates: predicates
|
||||||
|
@ -181,7 +182,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
|
||||||
) -> stable_mir::ty::GenericPredicates {
|
) -> stable_mir::ty::GenericPredicates {
|
||||||
let mut tables = self.0.borrow_mut();
|
let mut tables = self.0.borrow_mut();
|
||||||
let def_id = tables[def_id];
|
let def_id = tables[def_id];
|
||||||
let GenericPredicates { parent, predicates } = tables.tcx.explicit_predicates_of(def_id);
|
let GenericPredicates { parent, predicates, effects_min_tys: _ } =
|
||||||
|
tables.tcx.explicit_predicates_of(def_id);
|
||||||
stable_mir::ty::GenericPredicates {
|
stable_mir::ty::GenericPredicates {
|
||||||
parent: parent.map(|did| tables.trait_def(did)),
|
parent: parent.map(|did| tables.trait_def(did)),
|
||||||
predicates: predicates
|
predicates: predicates
|
||||||
|
|
|
@ -600,7 +600,7 @@ impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDefKind {
|
||||||
ty::GenericParamDefKind::Type { has_default, synthetic } => {
|
ty::GenericParamDefKind::Type { has_default, synthetic } => {
|
||||||
GenericParamDefKind::Type { has_default: *has_default, synthetic: *synthetic }
|
GenericParamDefKind::Type { has_default: *has_default, synthetic: *synthetic }
|
||||||
}
|
}
|
||||||
ty::GenericParamDefKind::Const { has_default, is_host_effect: _ } => {
|
ty::GenericParamDefKind::Const { has_default, is_host_effect: _, synthetic: _ } => {
|
||||||
GenericParamDefKind::Const { has_default: *has_default }
|
GenericParamDefKind::Const { has_default: *has_default }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,6 +194,14 @@ symbols! {
|
||||||
Display,
|
Display,
|
||||||
DoubleEndedIterator,
|
DoubleEndedIterator,
|
||||||
Duration,
|
Duration,
|
||||||
|
EffectsCompat,
|
||||||
|
EffectsIntersection,
|
||||||
|
EffectsIntersectionOutput,
|
||||||
|
EffectsMaybe,
|
||||||
|
EffectsNoRuntime,
|
||||||
|
EffectsRuntime,
|
||||||
|
EffectsTyCompat,
|
||||||
|
Effects__,
|
||||||
Encodable,
|
Encodable,
|
||||||
Encoder,
|
Encoder,
|
||||||
Enumerate,
|
Enumerate,
|
||||||
|
@ -1658,6 +1666,7 @@ symbols! {
|
||||||
rustc_reallocator,
|
rustc_reallocator,
|
||||||
rustc_regions,
|
rustc_regions,
|
||||||
rustc_reservation_impl,
|
rustc_reservation_impl,
|
||||||
|
rustc_runtime,
|
||||||
rustc_safe_intrinsic,
|
rustc_safe_intrinsic,
|
||||||
rustc_serialize,
|
rustc_serialize,
|
||||||
rustc_skip_during_method_dispatch,
|
rustc_skip_during_method_dispatch,
|
||||||
|
|
|
@ -4995,6 +4995,12 @@ fn point_at_assoc_type_restriction<G: EmissionGuarantee>(
|
||||||
let ty::ClauseKind::Projection(proj) = clause else {
|
let ty::ClauseKind::Projection(proj) = clause else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
// avoid ICEing since effects desugared associated types don't have names.
|
||||||
|
// this path should only be hit for `~const` on invalid places, so they
|
||||||
|
// will have an informative error already.
|
||||||
|
if tcx.is_effects_desugared_assoc_ty(proj.projection_term.def_id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let name = tcx.item_name(proj.projection_term.def_id);
|
let name = tcx.item_name(proj.projection_term.def_id);
|
||||||
let mut predicates = generics.predicates.iter().peekable();
|
let mut predicates = generics.predicates.iter().peekable();
|
||||||
let mut prev: Option<&hir::WhereBoundPredicate<'_>> = None;
|
let mut prev: Option<&hir::WhereBoundPredicate<'_>> = None;
|
||||||
|
|
|
@ -4,8 +4,9 @@ use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
|
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
|
||||||
use rustc_hir::intravisit::{self, Visitor};
|
use rustc_hir::intravisit::{self, Visitor};
|
||||||
use rustc_middle::query::Providers;
|
use rustc_middle::query::Providers;
|
||||||
use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt};
|
use rustc_middle::ty::{self, ImplTraitInTraitData, Ty, TyCtxt};
|
||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
|
use rustc_span::sym;
|
||||||
use rustc_span::symbol::kw;
|
use rustc_span::symbol::kw;
|
||||||
|
|
||||||
pub(crate) fn provide(providers: &mut Providers) {
|
pub(crate) fn provide(providers: &mut Providers) {
|
||||||
|
@ -14,6 +15,7 @@ pub(crate) fn provide(providers: &mut Providers) {
|
||||||
associated_item_def_ids,
|
associated_item_def_ids,
|
||||||
associated_items,
|
associated_items,
|
||||||
associated_types_for_impl_traits_in_associated_fn,
|
associated_types_for_impl_traits_in_associated_fn,
|
||||||
|
associated_type_for_effects,
|
||||||
associated_type_for_impl_trait_in_trait,
|
associated_type_for_impl_trait_in_trait,
|
||||||
impl_item_implementor_ids,
|
impl_item_implementor_ids,
|
||||||
..*providers
|
..*providers
|
||||||
|
@ -44,7 +46,8 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[DefId] {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.copied(),
|
.copied(),
|
||||||
),
|
)
|
||||||
|
.chain(tcx.associated_type_for_effects(def_id)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
hir::ItemKind::Impl(impl_) => {
|
hir::ItemKind::Impl(impl_) => {
|
||||||
|
@ -70,7 +73,8 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[DefId] {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.copied()
|
.copied()
|
||||||
})),
|
}))
|
||||||
|
.chain(tcx.associated_type_for_effects(def_id)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
|
_ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
|
||||||
|
@ -143,6 +147,7 @@ fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty
|
||||||
container: ty::TraitContainer,
|
container: ty::TraitContainer,
|
||||||
fn_has_self_parameter: has_self,
|
fn_has_self_parameter: has_self,
|
||||||
opt_rpitit_info: None,
|
opt_rpitit_info: None,
|
||||||
|
is_effects_desugaring: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,9 +167,138 @@ fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::A
|
||||||
container: ty::ImplContainer,
|
container: ty::ImplContainer,
|
||||||
fn_has_self_parameter: has_self,
|
fn_has_self_parameter: has_self,
|
||||||
opt_rpitit_info: None,
|
opt_rpitit_info: None,
|
||||||
|
is_effects_desugaring: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Given an `def_id` of a trait or a trait impl:
|
||||||
|
///
|
||||||
|
/// If `def_id` is a trait that has `#[const_trait]`, then it synthesizes
|
||||||
|
/// a new def id corresponding to a new associated type for the effects.
|
||||||
|
///
|
||||||
|
/// If `def_id` is an impl, then synthesize the associated type according
|
||||||
|
/// to the constness of the impl.
|
||||||
|
fn associated_type_for_effects(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> {
|
||||||
|
// don't synthesize the associated type even if the user has written `const_trait`
|
||||||
|
// if the effects feature is disabled.
|
||||||
|
if !tcx.features().effects {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let (feed, parent_did) = match tcx.def_kind(def_id) {
|
||||||
|
DefKind::Trait => {
|
||||||
|
let trait_def_id = def_id;
|
||||||
|
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);
|
||||||
|
|
||||||
|
let local_def_id = trait_assoc_ty.def_id();
|
||||||
|
let def_id = local_def_id.to_def_id();
|
||||||
|
|
||||||
|
// Copy span of the attribute.
|
||||||
|
trait_assoc_ty.def_ident_span(Some(span));
|
||||||
|
|
||||||
|
trait_assoc_ty.associated_item(ty::AssocItem {
|
||||||
|
name: kw::Empty,
|
||||||
|
kind: ty::AssocKind::Type,
|
||||||
|
def_id,
|
||||||
|
trait_item_def_id: None,
|
||||||
|
container: ty::TraitContainer,
|
||||||
|
fn_has_self_parameter: false,
|
||||||
|
opt_rpitit_info: None,
|
||||||
|
is_effects_desugaring: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
// No default type
|
||||||
|
trait_assoc_ty.defaultness(hir::Defaultness::Default { has_value: false });
|
||||||
|
|
||||||
|
trait_assoc_ty.is_type_alias_impl_trait(false);
|
||||||
|
|
||||||
|
(trait_assoc_ty, trait_def_id)
|
||||||
|
}
|
||||||
|
DefKind::Impl { .. } => {
|
||||||
|
let impl_def_id = def_id;
|
||||||
|
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 trait_assoc_id = tcx.associated_type_for_effects(trait_id)?;
|
||||||
|
|
||||||
|
// FIXME(effects): span
|
||||||
|
let span = tcx.def_ident_span(def_id).unwrap();
|
||||||
|
|
||||||
|
let impl_assoc_ty = tcx.at(span).create_def(def_id, kw::Empty, DefKind::AssocTy);
|
||||||
|
|
||||||
|
let local_def_id = impl_assoc_ty.def_id();
|
||||||
|
let def_id = local_def_id.to_def_id();
|
||||||
|
|
||||||
|
impl_assoc_ty.def_ident_span(Some(span));
|
||||||
|
|
||||||
|
impl_assoc_ty.associated_item(ty::AssocItem {
|
||||||
|
name: kw::Empty,
|
||||||
|
kind: ty::AssocKind::Type,
|
||||||
|
def_id,
|
||||||
|
trait_item_def_id: Some(trait_assoc_id),
|
||||||
|
container: ty::ImplContainer,
|
||||||
|
fn_has_self_parameter: false,
|
||||||
|
opt_rpitit_info: None,
|
||||||
|
is_effects_desugaring: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
// no default value.
|
||||||
|
impl_assoc_ty.defaultness(hir::Defaultness::Final);
|
||||||
|
|
||||||
|
// set the type of the associated type! If this is a const impl,
|
||||||
|
// we set to Maybe, otherwise we set to `Runtime`.
|
||||||
|
let type_def_id = if tcx.is_const_trait_impl_raw(impl_def_id.to_def_id()) {
|
||||||
|
tcx.require_lang_item(hir::LangItem::EffectsMaybe, Some(span))
|
||||||
|
} else {
|
||||||
|
tcx.require_lang_item(hir::LangItem::EffectsRuntime, Some(span))
|
||||||
|
};
|
||||||
|
// FIXME(effects): make impls use `Min` for their effect types
|
||||||
|
impl_assoc_ty.type_of(ty::EarlyBinder::bind(Ty::new_adt(
|
||||||
|
tcx,
|
||||||
|
tcx.adt_def(type_def_id),
|
||||||
|
ty::GenericArgs::empty(),
|
||||||
|
)));
|
||||||
|
|
||||||
|
(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:
|
/// Given an `fn_def_id` of a trait or a trait implementation:
|
||||||
///
|
///
|
||||||
/// if `fn_def_id` is a function defined inside a trait, then it synthesizes
|
/// if `fn_def_id` is a function defined inside a trait, then it synthesizes
|
||||||
|
@ -275,6 +409,7 @@ fn associated_type_for_impl_trait_in_trait(
|
||||||
fn_def_id: fn_def_id.to_def_id(),
|
fn_def_id: fn_def_id.to_def_id(),
|
||||||
opaque_def_id: opaque_ty_def_id.to_def_id(),
|
opaque_def_id: opaque_ty_def_id.to_def_id(),
|
||||||
}),
|
}),
|
||||||
|
is_effects_desugaring: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Copy visility of the containing function.
|
// Copy visility of the containing function.
|
||||||
|
@ -326,6 +461,7 @@ fn associated_type_for_impl_trait_in_impl(
|
||||||
container: ty::ImplContainer,
|
container: ty::ImplContainer,
|
||||||
fn_has_self_parameter: false,
|
fn_has_self_parameter: false,
|
||||||
opt_rpitit_info: Some(ImplTraitInTraitData::Impl { fn_def_id: impl_fn_def_id.to_def_id() }),
|
opt_rpitit_info: Some(ImplTraitInTraitData::Impl { fn_def_id: impl_fn_def_id.to_def_id() }),
|
||||||
|
is_effects_desugaring: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Copy visility of the containing function.
|
// Copy visility of the containing function.
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
use crate::inherent::{AdtDef, IntoKind, Ty};
|
||||||
|
use crate::lang_items::TraitSolverLangItem::{EffectsMaybe, EffectsNoRuntime, EffectsRuntime};
|
||||||
|
use crate::Interner;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum EffectKind {
|
||||||
|
Maybe,
|
||||||
|
Runtime,
|
||||||
|
NoRuntime,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EffectKind {
|
||||||
|
pub fn try_from_def_id<I: Interner>(tcx: I, def_id: I::DefId) -> Option<EffectKind> {
|
||||||
|
if tcx.is_lang_item(def_id, EffectsMaybe) {
|
||||||
|
Some(EffectKind::Maybe)
|
||||||
|
} else if tcx.is_lang_item(def_id, EffectsRuntime) {
|
||||||
|
Some(EffectKind::Runtime)
|
||||||
|
} else if tcx.is_lang_item(def_id, EffectsNoRuntime) {
|
||||||
|
Some(EffectKind::NoRuntime)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_def_id<I: Interner>(self, tcx: I) -> I::DefId {
|
||||||
|
let lang_item = match self {
|
||||||
|
EffectKind::Maybe => EffectsMaybe,
|
||||||
|
EffectKind::NoRuntime => EffectsNoRuntime,
|
||||||
|
EffectKind::Runtime => EffectsRuntime,
|
||||||
|
};
|
||||||
|
|
||||||
|
tcx.require_lang_item(lang_item)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_from_ty<I: Interner>(tcx: I, ty: I::Ty) -> Option<EffectKind> {
|
||||||
|
if let crate::Adt(def, _) = ty.kind() {
|
||||||
|
Self::try_from_def_id(tcx, def.def_id())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_ty<I: Interner>(self, tcx: I) -> I::Ty {
|
||||||
|
I::Ty::new_adt(tcx, tcx.adt_def(self.to_def_id(tcx)), Default::default())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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),
|
||||||
|
(Runtime, Runtime) => Some(Runtime),
|
||||||
|
(NoRuntime, NoRuntime) => Some(NoRuntime),
|
||||||
|
(Runtime, NoRuntime) | (NoRuntime, Runtime) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,11 @@ pub enum TraitSolverLangItem {
|
||||||
Destruct,
|
Destruct,
|
||||||
DiscriminantKind,
|
DiscriminantKind,
|
||||||
DynMetadata,
|
DynMetadata,
|
||||||
|
EffectsIntersection,
|
||||||
|
EffectsIntersectionOutput,
|
||||||
|
EffectsMaybe,
|
||||||
|
EffectsNoRuntime,
|
||||||
|
EffectsRuntime,
|
||||||
FnPtrTrait,
|
FnPtrTrait,
|
||||||
FusedIterator,
|
FusedIterator,
|
||||||
Future,
|
Future,
|
||||||
|
|
|
@ -35,6 +35,7 @@ mod macros;
|
||||||
mod binder;
|
mod binder;
|
||||||
mod canonical;
|
mod canonical;
|
||||||
mod const_kind;
|
mod const_kind;
|
||||||
|
mod effects;
|
||||||
mod flags;
|
mod flags;
|
||||||
mod generic_arg;
|
mod generic_arg;
|
||||||
mod interner;
|
mod interner;
|
||||||
|
@ -51,6 +52,7 @@ pub use canonical::*;
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(feature = "nightly")]
|
||||||
pub use codec::*;
|
pub use codec::*;
|
||||||
pub use const_kind::*;
|
pub use const_kind::*;
|
||||||
|
pub use effects::*;
|
||||||
pub use flags::*;
|
pub use flags::*;
|
||||||
pub use generic_arg::*;
|
pub use generic_arg::*;
|
||||||
pub use interner::*;
|
pub use interner::*;
|
||||||
|
|
|
@ -231,6 +231,7 @@
|
||||||
#![feature(let_chains)]
|
#![feature(let_chains)]
|
||||||
#![feature(link_llvm_intrinsics)]
|
#![feature(link_llvm_intrinsics)]
|
||||||
#![feature(macro_metavar_expr)]
|
#![feature(macro_metavar_expr)]
|
||||||
|
#![feature(marker_trait_attr)]
|
||||||
#![feature(min_exhaustive_patterns)]
|
#![feature(min_exhaustive_patterns)]
|
||||||
#![feature(min_specialization)]
|
#![feature(min_specialization)]
|
||||||
#![feature(multiple_supertrait_upcastable)]
|
#![feature(multiple_supertrait_upcastable)]
|
||||||
|
|
|
@ -1024,3 +1024,49 @@ pub trait FnPtr: Copy + Clone {
|
||||||
pub macro SmartPointer($item:item) {
|
pub macro SmartPointer($item:item) {
|
||||||
/* compiler built-in */
|
/* compiler built-in */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Support traits and types for the desugaring of const traits and
|
||||||
|
// `~const` bounds. Not supposed to be used by anything other than
|
||||||
|
// the compiler.
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[unstable(
|
||||||
|
feature = "effect_types",
|
||||||
|
issue = "none",
|
||||||
|
reason = "internal module for implementing effects"
|
||||||
|
)]
|
||||||
|
#[allow(missing_debug_implementations)] // these unit structs don't need `Debug` impls.
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
pub mod effects {
|
||||||
|
#[lang = "EffectsNoRuntime"]
|
||||||
|
pub struct NoRuntime;
|
||||||
|
#[lang = "EffectsMaybe"]
|
||||||
|
pub struct Maybe;
|
||||||
|
#[lang = "EffectsRuntime"]
|
||||||
|
pub struct Runtime;
|
||||||
|
|
||||||
|
#[lang = "EffectsCompat"]
|
||||||
|
pub trait Compat<#[rustc_runtime] const RUNTIME: bool> {}
|
||||||
|
|
||||||
|
impl Compat<false> for NoRuntime {}
|
||||||
|
impl Compat<true> for Runtime {}
|
||||||
|
impl<#[rustc_runtime] const RUNTIME: bool> Compat<RUNTIME> for Maybe {}
|
||||||
|
|
||||||
|
#[lang = "EffectsTyCompat"]
|
||||||
|
#[marker]
|
||||||
|
pub trait TyCompat<T: ?Sized> {}
|
||||||
|
|
||||||
|
impl<T: ?Sized> TyCompat<T> for T {}
|
||||||
|
impl<T: ?Sized> TyCompat<T> for Maybe {}
|
||||||
|
impl<T: ?Sized> TyCompat<Maybe> for T {}
|
||||||
|
|
||||||
|
#[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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -549,7 +549,7 @@ fn clean_generic_param_def<'tcx>(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ty::GenericParamDefKind::Const { has_default, is_host_effect } => (
|
ty::GenericParamDefKind::Const { has_default, synthetic, is_host_effect: _ } => (
|
||||||
def.name,
|
def.name,
|
||||||
GenericParamDefKind::Const {
|
GenericParamDefKind::Const {
|
||||||
ty: Box::new(clean_middle_ty(
|
ty: Box::new(clean_middle_ty(
|
||||||
|
@ -572,7 +572,7 @@ fn clean_generic_param_def<'tcx>(
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
is_host_effect,
|
synthetic,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
@ -628,13 +628,13 @@ fn clean_generic_param<'tcx>(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
hir::GenericParamKind::Const { ty, default, is_host_effect } => (
|
hir::GenericParamKind::Const { ty, default, synthetic, is_host_effect: _ } => (
|
||||||
param.name.ident().name,
|
param.name.ident().name,
|
||||||
GenericParamDefKind::Const {
|
GenericParamDefKind::Const {
|
||||||
ty: Box::new(clean_ty(ty, cx)),
|
ty: Box::new(clean_ty(ty, cx)),
|
||||||
default: default
|
default: default
|
||||||
.map(|ct| Box::new(ty::Const::from_anon_const(cx.tcx, ct.def_id).to_string())),
|
.map(|ct| Box::new(ty::Const::from_anon_const(cx.tcx, ct.def_id).to_string())),
|
||||||
is_host_effect,
|
synthetic,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
@ -1411,7 +1411,11 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
|
||||||
let mut generics = clean_ty_generics(
|
let mut generics = clean_ty_generics(
|
||||||
cx,
|
cx,
|
||||||
tcx.generics_of(assoc_item.def_id),
|
tcx.generics_of(assoc_item.def_id),
|
||||||
ty::GenericPredicates { parent: None, predicates },
|
ty::GenericPredicates {
|
||||||
|
parent: None,
|
||||||
|
predicates,
|
||||||
|
effects_min_tys: ty::List::empty(),
|
||||||
|
},
|
||||||
);
|
);
|
||||||
simplify::move_bounds_to_generic_parameters(&mut generics);
|
simplify::move_bounds_to_generic_parameters(&mut generics);
|
||||||
|
|
||||||
|
|
|
@ -1321,7 +1321,7 @@ pub(crate) enum GenericParamDefKind {
|
||||||
Lifetime { outlives: ThinVec<Lifetime> },
|
Lifetime { outlives: ThinVec<Lifetime> },
|
||||||
Type { bounds: ThinVec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
|
Type { bounds: ThinVec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
|
||||||
// Option<Box<String>> makes this type smaller than `Option<String>` would.
|
// Option<Box<String>> makes this type smaller than `Option<String>` would.
|
||||||
Const { ty: Box<Type>, default: Option<Box<String>>, is_host_effect: bool },
|
Const { ty: Box<Type>, default: Option<Box<String>>, synthetic: bool },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GenericParamDefKind {
|
impl GenericParamDefKind {
|
||||||
|
@ -1345,7 +1345,7 @@ impl GenericParamDef {
|
||||||
pub(crate) fn is_synthetic_param(&self) -> bool {
|
pub(crate) fn is_synthetic_param(&self) -> bool {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
GenericParamDefKind::Lifetime { .. } => false,
|
GenericParamDefKind::Lifetime { .. } => false,
|
||||||
GenericParamDefKind::Const { is_host_effect, .. } => is_host_effect,
|
GenericParamDefKind::Const { synthetic: is_host_effect, .. } => is_host_effect,
|
||||||
GenericParamDefKind::Type { synthetic, .. } => synthetic,
|
GenericParamDefKind::Type { synthetic, .. } => synthetic,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -466,7 +466,7 @@ impl FromWithTcx<clean::GenericParamDefKind> for GenericParamDefKind {
|
||||||
default: default.map(|x| (*x).into_tcx(tcx)),
|
default: default.map(|x| (*x).into_tcx(tcx)),
|
||||||
synthetic,
|
synthetic,
|
||||||
},
|
},
|
||||||
Const { ty, default, is_host_effect: _ } => GenericParamDefKind::Const {
|
Const { ty, default, synthetic: _ } => GenericParamDefKind::Const {
|
||||||
type_: (*ty).into_tcx(tcx),
|
type_: (*ty).into_tcx(tcx),
|
||||||
default: default.map(|x| *x),
|
default: default.map(|x| *x),
|
||||||
},
|
},
|
||||||
|
@ -501,14 +501,12 @@ impl FromWithTcx<clean::WherePredicate> for WherePredicate {
|
||||||
synthetic,
|
synthetic,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clean::GenericParamDefKind::Const {
|
clean::GenericParamDefKind::Const { ty, default, synthetic: _ } => {
|
||||||
ty,
|
GenericParamDefKind::Const {
|
||||||
default,
|
type_: (*ty).into_tcx(tcx),
|
||||||
is_host_effect: _,
|
default: default.map(|d| *d),
|
||||||
} => GenericParamDefKind::Const {
|
}
|
||||||
type_: (*ty).into_tcx(tcx),
|
}
|
||||||
default: default.map(|d| *d),
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
GenericParamDef { name, kind }
|
GenericParamDef { name, kind }
|
||||||
})
|
})
|
||||||
|
|
|
@ -104,15 +104,18 @@ fn main() {}
|
||||||
|
|
||||||
struct D;
|
struct D;
|
||||||
|
|
||||||
|
/* FIXME(effects)
|
||||||
impl const Drop for D {
|
impl const Drop for D {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Lint this, since it can be dropped in const contexts
|
// Lint this, since it can be dropped in const contexts
|
||||||
// FIXME(effects)
|
// FIXME(effects)
|
||||||
fn d(this: D) {}
|
const fn d(this: D) {}
|
||||||
|
//~^ ERROR: this could be a `const fn`
|
||||||
|
|
||||||
mod msrv {
|
mod msrv {
|
||||||
struct Foo(*const u8, &'static u8);
|
struct Foo(*const u8, &'static u8);
|
||||||
|
|
|
@ -104,15 +104,18 @@ fn main() {}
|
||||||
|
|
||||||
struct D;
|
struct D;
|
||||||
|
|
||||||
|
/* FIXME(effects)
|
||||||
impl const Drop for D {
|
impl const Drop for D {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Lint this, since it can be dropped in const contexts
|
// Lint this, since it can be dropped in const contexts
|
||||||
// FIXME(effects)
|
// FIXME(effects)
|
||||||
fn d(this: D) {}
|
fn d(this: D) {}
|
||||||
|
//~^ ERROR: this could be a `const fn`
|
||||||
|
|
||||||
mod msrv {
|
mod msrv {
|
||||||
struct Foo(*const u8, &'static u8);
|
struct Foo(*const u8, &'static u8);
|
||||||
|
|
|
@ -157,7 +157,18 @@ LL | const fn msrv_1_46() -> i32 {
|
||||||
| +++++
|
| +++++
|
||||||
|
|
||||||
error: this could be a `const fn`
|
error: this could be a `const fn`
|
||||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:122:9
|
--> tests/ui/missing_const_for_fn/could_be_const.rs:117:1
|
||||||
|
|
|
||||||
|
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
|
||||||
|
|
|
|
||||||
LL | / fn deref_ptr_can_be_const(self) -> usize {
|
LL | / fn deref_ptr_can_be_const(self) -> usize {
|
||||||
LL | |
|
LL | |
|
||||||
|
@ -171,7 +182,7 @@ LL | const fn deref_ptr_can_be_const(self) -> usize {
|
||||||
| +++++
|
| +++++
|
||||||
|
|
||||||
error: this could be a `const fn`
|
error: this could be a `const fn`
|
||||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:127:9
|
--> tests/ui/missing_const_for_fn/could_be_const.rs:130:9
|
||||||
|
|
|
|
||||||
LL | / fn deref_copied_val(self) -> usize {
|
LL | / fn deref_copied_val(self) -> usize {
|
||||||
LL | |
|
LL | |
|
||||||
|
@ -185,7 +196,7 @@ LL | const fn deref_copied_val(self) -> usize {
|
||||||
| +++++
|
| +++++
|
||||||
|
|
||||||
error: this could be a `const fn`
|
error: this could be a `const fn`
|
||||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:138:5
|
--> tests/ui/missing_const_for_fn/could_be_const.rs:141:5
|
||||||
|
|
|
|
||||||
LL | / fn union_access_can_be_const() {
|
LL | / fn union_access_can_be_const() {
|
||||||
LL | |
|
LL | |
|
||||||
|
@ -200,7 +211,7 @@ LL | const fn union_access_can_be_const() {
|
||||||
| +++++
|
| +++++
|
||||||
|
|
||||||
error: this could be a `const fn`
|
error: this could be a `const fn`
|
||||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:152:9
|
--> tests/ui/missing_const_for_fn/could_be_const.rs:155:9
|
||||||
|
|
|
|
||||||
LL | / pub fn new(strings: Vec<String>) -> Self {
|
LL | / pub fn new(strings: Vec<String>) -> Self {
|
||||||
LL | | Self { strings }
|
LL | | Self { strings }
|
||||||
|
@ -213,7 +224,7 @@ LL | pub const fn new(strings: Vec<String>) -> Self {
|
||||||
| +++++
|
| +++++
|
||||||
|
|
||||||
error: this could be a `const fn`
|
error: this could be a `const fn`
|
||||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:157:9
|
--> tests/ui/missing_const_for_fn/could_be_const.rs:160:9
|
||||||
|
|
|
|
||||||
LL | / pub fn empty() -> Self {
|
LL | / pub fn empty() -> Self {
|
||||||
LL | | Self { strings: Vec::new() }
|
LL | | Self { strings: Vec::new() }
|
||||||
|
@ -226,7 +237,7 @@ LL | pub const fn empty() -> Self {
|
||||||
| +++++
|
| +++++
|
||||||
|
|
||||||
error: this could be a `const fn`
|
error: this could be a `const fn`
|
||||||
--> tests/ui/missing_const_for_fn/could_be_const.rs:168:9
|
--> tests/ui/missing_const_for_fn/could_be_const.rs:171:9
|
||||||
|
|
|
|
||||||
LL | / pub fn new(text: String) -> Self {
|
LL | / pub fn new(text: String) -> Self {
|
||||||
LL | | let vec = Vec::new();
|
LL | | let vec = Vec::new();
|
||||||
|
@ -239,5 +250,5 @@ help: make the function `const`
|
||||||
LL | pub const fn new(text: String) -> Self {
|
LL | pub const fn new(text: String) -> Self {
|
||||||
| +++++
|
| +++++
|
||||||
|
|
||||||
error: aborting due to 17 previous errors
|
error: aborting due to 18 previous errors
|
||||||
|
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
//@ known-bug: #119717
|
|
||||||
#![feature(const_trait_impl, effects)]
|
|
||||||
|
|
||||||
use std::ops::{FromResidual, Try};
|
|
||||||
|
|
||||||
impl const FromResidual for T {
|
|
||||||
fn from_residual(t: T) -> _ {
|
|
||||||
t
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
//@ known-bug: #123664
|
|
||||||
#![feature(generic_const_exprs, effects)]
|
|
||||||
const fn with_positive<F: ~const Fn()>() {}
|
|
||||||
pub fn main() {}
|
|
|
@ -1,11 +0,0 @@
|
||||||
//@ known-bug: rust-lang/rust#124857
|
|
||||||
//@ compile-flags: -Znext-solver=coherence
|
|
||||||
|
|
||||||
#![feature(effects)]
|
|
||||||
|
|
||||||
#[const_trait]
|
|
||||||
trait Foo {}
|
|
||||||
|
|
||||||
impl const Foo for i32 {}
|
|
||||||
|
|
||||||
impl<T> const Foo for T where T: ~const Foo {}
|
|
|
@ -1,23 +0,0 @@
|
||||||
//@ known-bug: rust-lang/rust#126148
|
|
||||||
|
|
||||||
#![feature(effects)]
|
|
||||||
use std::ops::{FromResidual, Try};
|
|
||||||
|
|
||||||
struct TryMe;
|
|
||||||
struct Error;
|
|
||||||
|
|
||||||
impl const FromResidual<Error> for TryMe {}
|
|
||||||
|
|
||||||
impl const Try for TryMe {
|
|
||||||
type Output = ();
|
|
||||||
type Residual = Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
const fn t() -> TryMe {
|
|
||||||
TryMe?;
|
|
||||||
TryMe
|
|
||||||
}
|
|
||||||
|
|
||||||
const _: () = {
|
|
||||||
t();
|
|
||||||
};
|
|
|
@ -8,7 +8,8 @@
|
||||||
//
|
//
|
||||||
// FIXME(effects) add `const_trait` to `Fn` so we use `~const`
|
// FIXME(effects) add `const_trait` to `Fn` so we use `~const`
|
||||||
// FIXME(effects) restore `const_trait` to `Destruct`
|
// FIXME(effects) restore `const_trait` to `Destruct`
|
||||||
#![feature(const_trait_impl)]
|
#![allow(incomplete_features)]
|
||||||
|
#![feature(const_trait_impl, effects)]
|
||||||
#![crate_name = "foo"]
|
#![crate_name = "foo"]
|
||||||
|
|
||||||
use std::marker::Destruct;
|
use std::marker::Destruct;
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
//@ build-pass
|
//@ build-pass
|
||||||
|
//@ compile-flags: -Znext-solver
|
||||||
|
|
||||||
#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete
|
#![allow(incomplete_features)]
|
||||||
|
#![feature(const_trait_impl, effects)]
|
||||||
|
|
||||||
#[const_trait]
|
#[const_trait]
|
||||||
trait Func<T> {
|
trait Func<T> {
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
|
|
||||||
--> $DIR/const_trait_fn-issue-88433.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
|
|
||||||
|
|
||||||
warning: 1 warning emitted
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//@ known-bug: #110395
|
//@ known-bug: #110395
|
||||||
|
|
||||||
#![feature(generic_const_exprs, adt_const_params, const_trait_impl)]
|
#![feature(generic_const_exprs, adt_const_params, const_trait_impl, effects)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
// test `N + N` unifies with explicit function calls for non-builtin-types
|
// test `N + N` unifies with explicit function calls for non-builtin-types
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
error: const `impl` for trait `Add` which is not marked with `#[const_trait]`
|
||||||
|
--> $DIR/unify-op-with-fn-call.rs:10:12
|
||||||
|
|
|
||||||
|
LL | impl const std::ops::Add for Foo {
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
|
||||||
|
= note: adding a non-const method body in the future would be a breaking change
|
||||||
|
|
||||||
error[E0741]: `Foo` must implement `ConstParamTy` to be used as the type of a const generic parameter
|
error[E0741]: `Foo` must implement `ConstParamTy` to be used as the type of a const generic parameter
|
||||||
--> $DIR/unify-op-with-fn-call.rs:18:29
|
--> $DIR/unify-op-with-fn-call.rs:18:29
|
||||||
|
|
|
|
||||||
|
@ -45,48 +54,6 @@ help: try adding a `where` bound
|
||||||
LL | fn foo2<const N: usize>(a: Evaluatable2<{ N + N }>) where [(); { std::ops::Add::add(N, N) }]: {
|
LL | fn foo2<const N: usize>(a: Evaluatable2<{ N + N }>) where [(); { std::ops::Add::add(N, N) }]: {
|
||||||
| +++++++++++++++++++++++++++++++++++++++++
|
| +++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
error[E0015]: cannot call non-const operator in constants
|
error: aborting due to 5 previous errors
|
||||||
--> $DIR/unify-op-with-fn-call.rs:20:39
|
|
||||||
|
|
|
||||||
LL | fn foo<const N: Foo>(a: Evaluatable<{ N + N }>) {
|
|
||||||
| ^^^^^
|
|
||||||
|
|
|
||||||
note: impl defined here, but it is not `const`
|
|
||||||
--> $DIR/unify-op-with-fn-call.rs:10:1
|
|
||||||
|
|
|
||||||
LL | impl const std::ops::Add for Foo {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
|
|
||||||
help: add `#![feature(effects)]` to the crate attributes to enable
|
|
||||||
|
|
|
||||||
LL + #![feature(effects)]
|
|
||||||
|
|
|
||||||
|
|
||||||
error[E0015]: cannot call non-const fn `<Foo as Add>::add` in constants
|
For more information about this error, try `rustc --explain E0741`.
|
||||||
--> $DIR/unify-op-with-fn-call.rs:21:13
|
|
||||||
|
|
|
||||||
LL | bar::<{ std::ops::Add::add(N, N) }>();
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
|
|
||||||
help: add `#![feature(effects)]` to the crate attributes to enable
|
|
||||||
|
|
|
||||||
LL + #![feature(effects)]
|
|
||||||
|
|
|
||||||
|
|
||||||
error[E0015]: cannot call non-const fn `<usize as Add>::add` in constants
|
|
||||||
--> $DIR/unify-op-with-fn-call.rs:30:14
|
|
||||||
|
|
|
||||||
LL | bar2::<{ std::ops::Add::add(N, N) }>();
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
|
|
||||||
help: add `#![feature(effects)]` to the crate attributes to enable
|
|
||||||
|
|
|
||||||
LL + #![feature(effects)]
|
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to 7 previous errors
|
|
||||||
|
|
||||||
Some errors have detailed explanations: E0015, E0741.
|
|
||||||
For more information about an error, try `rustc --explain E0015`.
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//@ check-pass
|
//@ check-pass
|
||||||
|
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
#![feature(const_trait_impl, generic_const_exprs)]
|
#![feature(const_trait_impl, effects, generic_const_exprs)]
|
||||||
|
|
||||||
#[const_trait]
|
#[const_trait]
|
||||||
trait ConstName {
|
trait ConstName {
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#![feature(const_float_bits_conv)]
|
#![feature(const_float_bits_conv)]
|
||||||
#![feature(const_float_classify)]
|
#![feature(const_float_classify)]
|
||||||
#![feature(const_trait_impl, effects)]
|
#![feature(const_trait_impl, effects)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
// Don't promote
|
// Don't promote
|
||||||
const fn nop<T>(x: T) -> T { x }
|
const fn nop<T>(x: T) -> T { x }
|
||||||
|
|
|
@ -1,14 +1,5 @@
|
||||||
warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
|
|
||||||
--> $DIR/const-float-classify.rs:7: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: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]`
|
error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]`
|
||||||
--> $DIR/const-float-classify.rs:12:12
|
--> $DIR/const-float-classify.rs:13:12
|
||||||
|
|
|
|
||||||
LL | impl const PartialEq<NonDet> for bool {
|
LL | impl const PartialEq<NonDet> for bool {
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
@ -16,208 +7,5 @@ LL | impl const PartialEq<NonDet> for bool {
|
||||||
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
|
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
|
||||||
= note: adding a non-const method body in the future would be a breaking change
|
= note: adding a non-const method body in the future would be a breaking change
|
||||||
|
|
||||||
error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates
|
error: aborting due to 1 previous error
|
||||||
--> $DIR/const-float-classify.rs:12:6
|
|
||||||
|
|
|
||||||
LL | impl const PartialEq<NonDet> for bool {
|
|
||||||
| ^^^^^ unconstrained const parameter
|
|
||||||
|
|
|
||||||
= note: expressions using a const parameter must map each value to a distinct output value
|
|
||||||
= note: proving the result of expressions other than the parameter are unique is not supported
|
|
||||||
|
|
||||||
error[E0284]: type annotations needed
|
|
||||||
--> $DIR/const-float-classify.rs:21:35
|
|
||||||
|
|
|
||||||
LL | const _: () = assert!($a == $b);
|
|
||||||
| ^^ cannot infer the value of the constant `_`
|
|
||||||
...
|
|
||||||
LL | / suite! {
|
|
||||||
LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative]
|
|
||||||
LL | | -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet]
|
|
||||||
LL | | 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet]
|
|
||||||
... |
|
|
||||||
LL | | -1.0 / 0.0 => [ false, true, false, false, false, true]
|
|
||||||
LL | | }
|
|
||||||
| |_- in this macro invocation
|
|
||||||
|
|
|
||||||
note: required for `bool` to implement `PartialEq<NonDet>`
|
|
||||||
--> $DIR/const-float-classify.rs:12:12
|
|
||||||
|
|
|
||||||
LL | impl const PartialEq<NonDet> for bool {
|
|
||||||
| ----- ^^^^^^^^^^^^^^^^^ ^^^^
|
|
||||||
| |
|
|
||||||
| unsatisfied trait bound introduced here
|
|
||||||
= note: this error originates in the macro `const_assert` which comes from the expansion of the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error[E0284]: type annotations needed
|
|
||||||
--> $DIR/const-float-classify.rs:21:35
|
|
||||||
|
|
|
||||||
LL | const _: () = assert!($a == $b);
|
|
||||||
| ^^ cannot infer the value of the constant `_`
|
|
||||||
...
|
|
||||||
LL | / suite! {
|
|
||||||
LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative]
|
|
||||||
LL | | -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet]
|
|
||||||
LL | | 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet]
|
|
||||||
... |
|
|
||||||
LL | | -1.0 / 0.0 => [ false, true, false, false, false, true]
|
|
||||||
LL | | }
|
|
||||||
| |_- in this macro invocation
|
|
||||||
|
|
|
||||||
note: required for `bool` to implement `PartialEq<NonDet>`
|
|
||||||
--> $DIR/const-float-classify.rs:12:12
|
|
||||||
|
|
|
||||||
LL | impl const PartialEq<NonDet> for bool {
|
|
||||||
| ----- ^^^^^^^^^^^^^^^^^ ^^^^
|
|
||||||
| |
|
|
||||||
| unsatisfied trait bound introduced here
|
|
||||||
= note: this error originates in the macro `const_assert` which comes from the expansion of the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error[E0284]: type annotations needed
|
|
||||||
--> $DIR/const-float-classify.rs:21:35
|
|
||||||
|
|
|
||||||
LL | const _: () = assert!($a == $b);
|
|
||||||
| ^^ cannot infer the value of the constant `_`
|
|
||||||
...
|
|
||||||
LL | / suite! {
|
|
||||||
LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative]
|
|
||||||
LL | | -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet]
|
|
||||||
LL | | 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet]
|
|
||||||
... |
|
|
||||||
LL | | -1.0 / 0.0 => [ false, true, false, false, false, true]
|
|
||||||
LL | | }
|
|
||||||
| |_- in this macro invocation
|
|
||||||
|
|
|
||||||
note: required for `bool` to implement `PartialEq<NonDet>`
|
|
||||||
--> $DIR/const-float-classify.rs:12:12
|
|
||||||
|
|
|
||||||
LL | impl const PartialEq<NonDet> for bool {
|
|
||||||
| ----- ^^^^^^^^^^^^^^^^^ ^^^^
|
|
||||||
| |
|
|
||||||
| unsatisfied trait bound introduced here
|
|
||||||
= note: this error originates in the macro `const_assert` which comes from the expansion of the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error[E0284]: type annotations needed
|
|
||||||
--> $DIR/const-float-classify.rs:21:35
|
|
||||||
|
|
|
||||||
LL | const _: () = assert!($a == $b);
|
|
||||||
| ^^ cannot infer the value of the constant `_`
|
|
||||||
...
|
|
||||||
LL | / suite! {
|
|
||||||
LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative]
|
|
||||||
LL | | -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet]
|
|
||||||
LL | | 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet]
|
|
||||||
... |
|
|
||||||
LL | | -1.0 / 0.0 => [ false, true, false, false, false, true]
|
|
||||||
LL | | }
|
|
||||||
| |_- in this macro invocation
|
|
||||||
|
|
|
||||||
note: required for `bool` to implement `PartialEq<NonDet>`
|
|
||||||
--> $DIR/const-float-classify.rs:12:12
|
|
||||||
|
|
|
||||||
LL | impl const PartialEq<NonDet> for bool {
|
|
||||||
| ----- ^^^^^^^^^^^^^^^^^ ^^^^
|
|
||||||
| |
|
|
||||||
| unsatisfied trait bound introduced here
|
|
||||||
= note: this error originates in the macro `const_assert` which comes from the expansion of the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error[E0284]: type annotations needed
|
|
||||||
--> $DIR/const-float-classify.rs:21:35
|
|
||||||
|
|
|
||||||
LL | const _: () = assert!($a == $b);
|
|
||||||
| ^^ cannot infer the value of the constant `_`
|
|
||||||
...
|
|
||||||
LL | / suite! {
|
|
||||||
LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative]
|
|
||||||
LL | | -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet]
|
|
||||||
LL | | 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet]
|
|
||||||
... |
|
|
||||||
LL | | -1.0 / 0.0 => [ false, true, false, false, false, true]
|
|
||||||
LL | | }
|
|
||||||
| |_- in this macro invocation
|
|
||||||
|
|
|
||||||
note: required for `bool` to implement `PartialEq<NonDet>`
|
|
||||||
--> $DIR/const-float-classify.rs:12:12
|
|
||||||
|
|
|
||||||
LL | impl const PartialEq<NonDet> for bool {
|
|
||||||
| ----- ^^^^^^^^^^^^^^^^^ ^^^^
|
|
||||||
| |
|
|
||||||
| unsatisfied trait bound introduced here
|
|
||||||
= note: this error originates in the macro `const_assert` which comes from the expansion of the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error[E0284]: type annotations needed
|
|
||||||
--> $DIR/const-float-classify.rs:21:35
|
|
||||||
|
|
|
||||||
LL | const _: () = assert!($a == $b);
|
|
||||||
| ^^ cannot infer the value of the constant `_`
|
|
||||||
...
|
|
||||||
LL | / suite! {
|
|
||||||
LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative]
|
|
||||||
LL | | -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet]
|
|
||||||
LL | | 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet]
|
|
||||||
... |
|
|
||||||
LL | | -1.0 / 0.0 => [ false, true, false, false, false, true]
|
|
||||||
LL | | }
|
|
||||||
| |_- in this macro invocation
|
|
||||||
|
|
|
||||||
note: required for `bool` to implement `PartialEq<NonDet>`
|
|
||||||
--> $DIR/const-float-classify.rs:12:12
|
|
||||||
|
|
|
||||||
LL | impl const PartialEq<NonDet> for bool {
|
|
||||||
| ----- ^^^^^^^^^^^^^^^^^ ^^^^
|
|
||||||
| |
|
|
||||||
| unsatisfied trait bound introduced here
|
|
||||||
= note: this error originates in the macro `const_assert` which comes from the expansion of the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error[E0284]: type annotations needed
|
|
||||||
--> $DIR/const-float-classify.rs:21:35
|
|
||||||
|
|
|
||||||
LL | const _: () = assert!($a == $b);
|
|
||||||
| ^^ cannot infer the value of the constant `_`
|
|
||||||
...
|
|
||||||
LL | / suite! {
|
|
||||||
LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative]
|
|
||||||
LL | | -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet]
|
|
||||||
LL | | 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet]
|
|
||||||
... |
|
|
||||||
LL | | -1.0 / 0.0 => [ false, true, false, false, false, true]
|
|
||||||
LL | | }
|
|
||||||
| |_- in this macro invocation
|
|
||||||
|
|
|
||||||
note: required for `bool` to implement `PartialEq<NonDet>`
|
|
||||||
--> $DIR/const-float-classify.rs:12:12
|
|
||||||
|
|
|
||||||
LL | impl const PartialEq<NonDet> for bool {
|
|
||||||
| ----- ^^^^^^^^^^^^^^^^^ ^^^^
|
|
||||||
| |
|
|
||||||
| unsatisfied trait bound introduced here
|
|
||||||
= note: this error originates in the macro `const_assert` which comes from the expansion of the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error[E0284]: type annotations needed
|
|
||||||
--> $DIR/const-float-classify.rs:21:35
|
|
||||||
|
|
|
||||||
LL | const _: () = assert!($a == $b);
|
|
||||||
| ^^ cannot infer the value of the constant `_`
|
|
||||||
...
|
|
||||||
LL | / suite! {
|
|
||||||
LL | | [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative]
|
|
||||||
LL | | -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet]
|
|
||||||
LL | | 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet]
|
|
||||||
... |
|
|
||||||
LL | | -1.0 / 0.0 => [ false, true, false, false, false, true]
|
|
||||||
LL | | }
|
|
||||||
| |_- in this macro invocation
|
|
||||||
|
|
|
||||||
note: required for `bool` to implement `PartialEq<NonDet>`
|
|
||||||
--> $DIR/const-float-classify.rs:12:12
|
|
||||||
|
|
|
||||||
LL | impl const PartialEq<NonDet> for bool {
|
|
||||||
| ----- ^^^^^^^^^^^^^^^^^ ^^^^
|
|
||||||
| |
|
|
||||||
| unsatisfied trait bound introduced here
|
|
||||||
= note: this error originates in the macro `const_assert` which comes from the expansion of the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error: aborting due to 10 previous errors; 1 warning emitted
|
|
||||||
|
|
||||||
Some errors have detailed explanations: E0207, E0284.
|
|
||||||
For more information about an error, try `rustc --explain E0207`.
|
|
||||||
|
|
|
@ -4,8 +4,9 @@
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
#![feature(try_trait_v2)]
|
#![feature(try_trait_v2)]
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl, effects)]
|
||||||
#![feature(const_try)]
|
#![feature(const_try)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
use std::ops::{ControlFlow, FromResidual, Try};
|
use std::ops::{ControlFlow, FromResidual, Try};
|
||||||
|
|
||||||
|
|
|
@ -1,37 +1,20 @@
|
||||||
error[E0015]: `?` cannot determine the branch of `TryMe` in constant functions
|
error: const `impl` for trait `FromResidual` which is not marked with `#[const_trait]`
|
||||||
--> $DIR/const-try.rs:33:5
|
--> $DIR/const-try.rs:16:12
|
||||||
|
|
|
||||||
LL | TryMe?;
|
|
||||||
| ^^^^^^
|
|
||||||
|
|
|
||||||
note: impl defined here, but it is not `const`
|
|
||||||
--> $DIR/const-try.rs:21:1
|
|
||||||
|
|
|
||||||
LL | impl const Try for TryMe {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
|
||||||
help: add `#![feature(effects)]` to the crate attributes to enable
|
|
||||||
|
|
|
||||||
LL + #![feature(effects)]
|
|
||||||
|
|
|
||||||
|
|
||||||
error[E0015]: `?` cannot convert from residual of `TryMe` in constant functions
|
|
||||||
--> $DIR/const-try.rs:33:5
|
|
||||||
|
|
|
||||||
LL | TryMe?;
|
|
||||||
| ^^^^^^
|
|
||||||
|
|
|
||||||
note: impl defined here, but it is not `const`
|
|
||||||
--> $DIR/const-try.rs:15:1
|
|
||||||
|
|
|
|
||||||
LL | impl const FromResidual<Error> for TryMe {
|
LL | impl const FromResidual<Error> for TryMe {
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
|
||||||
help: add `#![feature(effects)]` to the crate attributes to enable
|
|
||||||
|
|
|
|
||||||
LL + #![feature(effects)]
|
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
|
||||||
|
= note: adding a non-const method body in the future would be a breaking change
|
||||||
|
|
||||||
|
error: const `impl` for trait `Try` which is not marked with `#[const_trait]`
|
||||||
|
--> $DIR/const-try.rs:22:12
|
||||||
|
|
|
|
||||||
|
LL | impl const Try for TryMe {
|
||||||
|
| ^^^
|
||||||
|
|
|
||||||
|
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
|
||||||
|
= note: adding a non-const method body in the future would be a breaking change
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0015`.
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//@ known-bug: #102498
|
//@ known-bug: #102498
|
||||||
|
|
||||||
#![feature(const_trait_impl, generic_const_exprs)]
|
#![feature(const_trait_impl, effects, generic_const_exprs)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
#[const_trait]
|
#[const_trait]
|
||||||
pub trait Tr {
|
pub trait Tr {
|
||||||
|
|
|
@ -1,36 +1,21 @@
|
||||||
warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
|
error[E0308]: mismatched types
|
||||||
--> $DIR/constifconst-call-in-const-position.rs:3:30
|
--> $DIR/constifconst-call-in-const-position.rs:17:38
|
||||||
|
|
|
||||||
LL | #![feature(const_trait_impl, generic_const_exprs)]
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
|
|
||||||
= note: `#[warn(incomplete_features)]` on by default
|
|
||||||
|
|
||||||
error[E0015]: cannot call non-const fn `<T as Tr>::a` in constants
|
|
||||||
--> $DIR/constifconst-call-in-const-position.rs:17:9
|
|
||||||
|
|
|
||||||
LL | [0; T::a()]
|
|
||||||
| ^^^^^^
|
|
||||||
|
|
|
||||||
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
|
|
||||||
help: add `#![feature(effects)]` to the crate attributes to enable
|
|
||||||
|
|
|
||||||
LL + #![feature(effects)]
|
|
||||||
|
|
|
||||||
|
|
||||||
error[E0015]: cannot call non-const fn `<T as Tr>::a` in constants
|
|
||||||
--> $DIR/constifconst-call-in-const-position.rs:16:38
|
|
||||||
|
|
|
|
||||||
LL | const fn foo<T: ~const Tr>() -> [u8; T::a()] {
|
LL | const fn foo<T: ~const Tr>() -> [u8; T::a()] {
|
||||||
| ^^^^^^
|
| ^^^^^^ expected `false`, found `host`
|
||||||
|
|
|
||||||
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
|
|
||||||
help: add `#![feature(effects)]` to the crate attributes to enable
|
|
||||||
|
|
|
||||||
LL + #![feature(effects)]
|
|
||||||
|
|
|
|
||||||
|
= note: expected constant `false`
|
||||||
|
found constant `host`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors; 1 warning emitted
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/constifconst-call-in-const-position.rs:18:9
|
||||||
|
|
|
||||||
|
LL | [0; T::a()]
|
||||||
|
| ^^^^^^ expected `false`, found `host`
|
||||||
|
|
|
||||||
|
= note: expected constant `false`
|
||||||
|
found constant `host`
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0015`.
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
struct A();
|
struct A();
|
||||||
|
|
||||||
impl const Drop for A {
|
impl const Drop for A {
|
||||||
|
//~^ ERROR const `impl` for trait `Drop` which is not marked with `#[const_trait]`
|
||||||
fn drop(&mut self) {}
|
fn drop(&mut self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,14 @@
|
||||||
|
error: const `impl` for trait `Drop` which is not marked with `#[const_trait]`
|
||||||
|
--> $DIR/promoted-const-drop.rs:6:12
|
||||||
|
|
|
||||||
|
LL | impl const Drop for A {
|
||||||
|
| ^^^^
|
||||||
|
|
|
||||||
|
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
|
||||||
|
= note: adding a non-const method body in the future would be a breaking change
|
||||||
|
|
||||||
error[E0716]: temporary value dropped while borrowed
|
error[E0716]: temporary value dropped while borrowed
|
||||||
--> $DIR/promoted-const-drop.rs:13:26
|
--> $DIR/promoted-const-drop.rs:14:26
|
||||||
|
|
|
|
||||||
LL | let _: &'static A = &A();
|
LL | let _: &'static A = &A();
|
||||||
| ---------- ^^^ creates a temporary value which is freed while still in use
|
| ---------- ^^^ creates a temporary value which is freed while still in use
|
||||||
|
@ -10,7 +19,7 @@ LL | }
|
||||||
| - temporary value is freed at the end of this statement
|
| - temporary value is freed at the end of this statement
|
||||||
|
|
||||||
error[E0716]: temporary value dropped while borrowed
|
error[E0716]: temporary value dropped while borrowed
|
||||||
--> $DIR/promoted-const-drop.rs:14:28
|
--> $DIR/promoted-const-drop.rs:15:28
|
||||||
|
|
|
|
||||||
LL | let _: &'static [A] = &[C];
|
LL | let _: &'static [A] = &[C];
|
||||||
| ------------ ^^^ creates a temporary value which is freed while still in use
|
| ------------ ^^^ creates a temporary value which is freed while still in use
|
||||||
|
@ -19,6 +28,6 @@ LL | let _: &'static [A] = &[C];
|
||||||
LL | }
|
LL | }
|
||||||
| - temporary value is freed at the end of this statement
|
| - temporary value is freed at the end of this statement
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0716`.
|
For more information about this error, try `rustc --explain E0716`.
|
||||||
|
|
|
@ -1,10 +1,31 @@
|
||||||
error[E0493]: destructor of `Panic` cannot be evaluated at compile-time
|
error: const `impl` for trait `Drop` which is not marked with `#[const_trait]`
|
||||||
|
--> $DIR/promoted_const_call.rs:7:12
|
||||||
|
|
|
||||||
|
LL | impl const Drop for Panic { fn drop(&mut self) { panic!(); } }
|
||||||
|
| ^^^^
|
||||||
|
|
|
||||||
|
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
|
||||||
|
= note: adding a non-const method body in the future would be a breaking change
|
||||||
|
|
||||||
|
error[E0716]: temporary value dropped while borrowed
|
||||||
|
--> $DIR/promoted_const_call.rs:11:26
|
||||||
|
|
|
||||||
|
LL | let _: &'static _ = &id(&Panic);
|
||||||
|
| ---------- ^^^^^^^^^^ creates a temporary value which is freed while still in use
|
||||||
|
| |
|
||||||
|
| type annotation requires that borrow lasts for `'static`
|
||||||
|
...
|
||||||
|
LL | };
|
||||||
|
| - temporary value is freed at the end of this statement
|
||||||
|
|
||||||
|
error[E0716]: temporary value dropped while borrowed
|
||||||
--> $DIR/promoted_const_call.rs:11:30
|
--> $DIR/promoted_const_call.rs:11:30
|
||||||
|
|
|
|
||||||
LL | let _: &'static _ = &id(&Panic);
|
LL | let _: &'static _ = &id(&Panic);
|
||||||
| ^^^^^ - value is dropped here
|
| ---------- ^^^^^ - temporary value is freed at the end of this statement
|
||||||
| |
|
| | |
|
||||||
| the destructor for this type cannot be evaluated in constants
|
| | creates a temporary value which is freed while still in use
|
||||||
|
| type annotation requires that borrow lasts for `'static`
|
||||||
|
|
||||||
error[E0716]: temporary value dropped while borrowed
|
error[E0716]: temporary value dropped while borrowed
|
||||||
--> $DIR/promoted_const_call.rs:17:26
|
--> $DIR/promoted_const_call.rs:17:26
|
||||||
|
@ -48,7 +69,6 @@ LL | let _: &'static _ = &&(Panic, 0).1;
|
||||||
LL | }
|
LL | }
|
||||||
| - temporary value is freed at the end of this statement
|
| - temporary value is freed at the end of this statement
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error: aborting due to 7 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0493, E0716.
|
For more information about this error, try `rustc --explain E0716`.
|
||||||
For more information about an error, try `rustc --explain E0493`.
|
|
||||||
|
|
|
@ -16,15 +16,5 @@ LL | impl const Default for Data {
|
||||||
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
|
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
|
||||||
= note: adding a non-const method body in the future would be a breaking change
|
= note: adding a non-const method body in the future would be a breaking change
|
||||||
|
|
||||||
error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates
|
error: aborting due to 1 previous error; 1 warning emitted
|
||||||
--> $DIR/rustc-impl-const-stability.rs:15:6
|
|
||||||
|
|
|
||||||
LL | impl const Default for Data {
|
|
||||||
| ^^^^^ unconstrained const parameter
|
|
||||||
|
|
|
||||||
= note: expressions using a const parameter must map each value to a distinct output value
|
|
||||||
= note: proving the result of expressions other than the parameter are unique is not supported
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors; 1 warning emitted
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0207`.
|
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
|
|
||||||
--> $DIR/assoc-type-const-bound-usage-0.rs:6: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 `T: Trait` is not satisfied
|
|
||||||
--> $DIR/assoc-type-const-bound-usage-0.rs:21:6
|
|
||||||
|
|
|
||||||
LL | <T as /* FIXME: ~const */ Trait>::Assoc::func()
|
|
||||||
| ^ the trait `Trait` is not implemented for `T`
|
|
||||||
|
|
|
||||||
help: consider further restricting this bound
|
|
||||||
|
|
|
||||||
LL | const fn qualified<T: ~const Trait + Trait>() -> i32 {
|
|
||||||
| +++++++
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error; 1 warning emitted
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0277`.
|
|
|
@ -1,9 +1,7 @@
|
||||||
// FIXME(effects): Collapse the revisions into one once we support `<Ty as ~const Trait>::Proj`.
|
//@ known-bug: unknown
|
||||||
//@ revisions: unqualified qualified
|
|
||||||
//@[unqualified] check-pass
|
|
||||||
//@[qualified] known-bug: unknown
|
|
||||||
|
|
||||||
#![feature(const_trait_impl, effects)] //[unqualified]~ WARN the feature `effects` is incomplete
|
#![allow(incomplete_features)]
|
||||||
|
#![feature(const_trait_impl, effects)]
|
||||||
|
|
||||||
#[const_trait]
|
#[const_trait]
|
||||||
trait Trait {
|
trait Trait {
|
||||||
|
@ -11,14 +9,12 @@ trait Trait {
|
||||||
fn func() -> i32;
|
fn func() -> i32;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unqualified)]
|
|
||||||
const fn unqualified<T: ~const Trait>() -> i32 {
|
const fn unqualified<T: ~const Trait>() -> i32 {
|
||||||
T::Assoc::func()
|
T::Assoc::func()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(qualified)]
|
|
||||||
const fn qualified<T: ~const Trait>() -> i32 {
|
const fn qualified<T: ~const Trait>() -> i32 {
|
||||||
<T as /* FIXME: ~const */ Trait>::Assoc::func()
|
<T as Trait>::Assoc::func()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
error[E0277]: the trait bound `Trait::{synthetic#0}: Compat` is not satisfied
|
||||||
|
--> $DIR/assoc-type-const-bound-usage-0.rs:13:5
|
||||||
|
|
|
||||||
|
LL | T::Assoc::func()
|
||||||
|
| ^^^^^^^^ the trait `Compat` is not implemented for `Trait::{synthetic#0}`
|
||||||
|
|
|
||||||
|
note: required by a bound in `Trait::func`
|
||||||
|
--> $DIR/assoc-type-const-bound-usage-0.rs:6:1
|
||||||
|
|
|
||||||
|
LL | #[const_trait]
|
||||||
|
| ^^^^^^^^^^^^^^ required by this bound in `Trait::func`
|
||||||
|
...
|
||||||
|
LL | fn func() -> i32;
|
||||||
|
| ---- required by a bound in this associated function
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `Trait::{synthetic#0}: Compat` is not satisfied
|
||||||
|
--> $DIR/assoc-type-const-bound-usage-0.rs:17:5
|
||||||
|
|
|
||||||
|
LL | <T as Trait>::Assoc::func()
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^ the trait `Compat` is not implemented for `Trait::{synthetic#0}`
|
||||||
|
|
|
||||||
|
note: required by a bound in `Trait::func`
|
||||||
|
--> $DIR/assoc-type-const-bound-usage-0.rs:6:1
|
||||||
|
|
|
||||||
|
LL | #[const_trait]
|
||||||
|
| ^^^^^^^^^^^^^^ required by this bound in `Trait::func`
|
||||||
|
...
|
||||||
|
LL | fn func() -> i32;
|
||||||
|
| ---- required by a bound in this associated function
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
|
@ -1,11 +0,0 @@
|
||||||
warning: the feature `effects` is incomplete and may not be safe to use and/or cause compiler crashes
|
|
||||||
--> $DIR/assoc-type-const-bound-usage-0.rs:6: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
|
|
||||||
|
|
||||||
warning: 1 warning emitted
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
error[E0277]: the trait bound `T: Trait` is not satisfied
|
|
||||||
--> $DIR/assoc-type-const-bound-usage-1.rs:23:43
|
|
||||||
|
|
|
||||||
LL | fn qualified<T: const Trait>() -> Type<{ <T as /* FIXME: const */ Trait>::Assoc::func() }> {
|
|
||||||
| ^ the trait `Trait` is not implemented for `T`
|
|
||||||
|
|
|
||||||
help: consider further restricting this bound
|
|
||||||
|
|
|
||||||
LL | fn qualified<T: const Trait + Trait>() -> Type<{ <T as /* FIXME: const */ Trait>::Assoc::func() }> {
|
|
||||||
| +++++++
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0277`.
|
|
|
@ -1,7 +1,5 @@
|
||||||
// FIXME(effects): Collapse the revisions into one once we support `<Ty as const Trait>::Proj`.
|
//@ known-bug: unknown
|
||||||
//@ revisions: unqualified qualified
|
// FIXME(effects)
|
||||||
//@[unqualified] check-pass
|
|
||||||
//@[qualified] known-bug: unknown
|
|
||||||
|
|
||||||
#![feature(const_trait_impl, effects, generic_const_exprs)]
|
#![feature(const_trait_impl, effects, generic_const_exprs)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
|
@ -14,13 +12,11 @@ trait Trait {
|
||||||
|
|
||||||
struct Type<const N: i32>;
|
struct Type<const N: i32>;
|
||||||
|
|
||||||
#[cfg(unqualified)]
|
|
||||||
fn unqualified<T: const Trait>() -> Type<{ T::Assoc::func() }> {
|
fn unqualified<T: const Trait>() -> Type<{ T::Assoc::func() }> {
|
||||||
Type
|
Type
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(qualified)]
|
fn qualified<T: const Trait>() -> Type<{ <T as Trait>::Assoc::func() }> {
|
||||||
fn qualified<T: const Trait>() -> Type<{ <T as /* FIXME: const */ Trait>::Assoc::func() }> {
|
|
||||||
Type
|
Type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
error[E0277]: the trait bound `Trait::{synthetic#0}: Compat` is not satisfied
|
||||||
|
--> $DIR/assoc-type-const-bound-usage-1.rs:15:44
|
||||||
|
|
|
||||||
|
LL | fn unqualified<T: const Trait>() -> Type<{ T::Assoc::func() }> {
|
||||||
|
| ^^^^^^^^ the trait `Compat` is not implemented for `Trait::{synthetic#0}`
|
||||||
|
|
|
||||||
|
note: required by a bound in `Trait::func`
|
||||||
|
--> $DIR/assoc-type-const-bound-usage-1.rs:7:1
|
||||||
|
|
|
||||||
|
LL | #[const_trait]
|
||||||
|
| ^^^^^^^^^^^^^^ required by this bound in `Trait::func`
|
||||||
|
...
|
||||||
|
LL | fn func() -> i32;
|
||||||
|
| ---- required by a bound in this associated function
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `Trait::{synthetic#0}: Compat` is not satisfied
|
||||||
|
--> $DIR/assoc-type-const-bound-usage-1.rs:19:42
|
||||||
|
|
|
||||||
|
LL | fn qualified<T: const Trait>() -> Type<{ <T as Trait>::Assoc::func() }> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^ the trait `Compat` is not implemented for `Trait::{synthetic#0}`
|
||||||
|
|
|
||||||
|
note: required by a bound in `Trait::func`
|
||||||
|
--> $DIR/assoc-type-const-bound-usage-1.rs:7:1
|
||||||
|
|
|
||||||
|
LL | #[const_trait]
|
||||||
|
| ^^^^^^^^^^^^^^ required by this bound in `Trait::func`
|
||||||
|
...
|
||||||
|
LL | fn func() -> i32;
|
||||||
|
| ---- required by a bound in this associated function
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
|
@ -32,12 +32,14 @@ trait Foo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl const Foo for NonConstAdd {
|
impl const Foo for NonConstAdd {
|
||||||
type Bar = NonConstAdd; //~ ERROR the trait bound `NonConstAdd: ~const Add` is not satisfied
|
type Bar = NonConstAdd;
|
||||||
|
// FIXME(effects) ERROR the trait bound `NonConstAdd: ~const Add` is not satisfied
|
||||||
}
|
}
|
||||||
|
|
||||||
#[const_trait]
|
#[const_trait]
|
||||||
trait Baz {
|
trait Baz {
|
||||||
type Qux: Add;
|
type Qux: Add;
|
||||||
|
//~^ ERROR the trait bound
|
||||||
}
|
}
|
||||||
|
|
||||||
impl const Baz for NonConstAdd {
|
impl const Baz for NonConstAdd {
|
||||||
|
|
|
@ -7,18 +7,16 @@ LL | #![feature(const_trait_impl, effects)]
|
||||||
= note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
|
= note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
|
||||||
= note: `#[warn(incomplete_features)]` on by default
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
error[E0277]: the trait bound `NonConstAdd: ~const Add` is not satisfied
|
error[E0277]: the trait bound `Add::{synthetic#0}: Compat` is not satisfied
|
||||||
--> $DIR/assoc-type.rs:35:16
|
--> $DIR/assoc-type.rs:41:15
|
||||||
|
|
|
|
||||||
LL | type Bar = NonConstAdd;
|
LL | type Qux: Add;
|
||||||
| ^^^^^^^^^^^ the trait `~const Add` is not implemented for `NonConstAdd`
|
| ^^^ the trait `Compat` is not implemented for `Add::{synthetic#0}`
|
||||||
|
|
|
|
||||||
= help: the trait `Add` is implemented for `NonConstAdd`
|
help: consider further restricting the associated type
|
||||||
note: required by a bound in `Foo::Bar`
|
|
||||||
--> $DIR/assoc-type.rs:31:15
|
|
||||||
|
|
|
|
||||||
LL | type Bar: ~const Add;
|
LL | trait Baz where Add::{synthetic#0}: Compat {
|
||||||
| ^^^^^^^^^^ required by this bound in `Foo::Bar`
|
| ++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
error: aborting due to 1 previous error; 1 warning emitted
|
error: aborting due to 1 previous error; 1 warning emitted
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#![feature(const_trait_impl, effects)] //~ WARN the feature `effects` is incomplete
|
#![allow(incomplete_features)]
|
||||||
|
#![feature(const_trait_impl, effects)]
|
||||||
|
|
||||||
#[const_trait]
|
#[const_trait]
|
||||||
pub trait MyTrait {
|
pub trait MyTrait {
|
||||||
|
|
|
@ -7,13 +7,21 @@ LL | #![feature(const_trait_impl, effects)]
|
||||||
= note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
|
= note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
|
||||||
= note: `#[warn(incomplete_features)]` on by default
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
error[E0277]: the trait bound `u32: ~const Plus` is not satisfied
|
error[E0277]: the trait bound `Runtime: ~const Compat` is not satisfied
|
||||||
--> $DIR/call-const-trait-method-fail.rs:25:5
|
--> $DIR/call-const-trait-method-fail.rs:25:5
|
||||||
|
|
|
|
||||||
LL | a.plus(b)
|
LL | a.plus(b)
|
||||||
| ^ the trait `~const Plus` is not implemented for `u32`
|
| ^ the trait `~const Compat` is not implemented for `Runtime`
|
||||||
|
|
|
|
||||||
= help: the trait `Plus` is implemented for `u32`
|
= help: the trait `Compat` is implemented for `Runtime`
|
||||||
|
note: required by a bound in `Plus::plus`
|
||||||
|
--> $DIR/call-const-trait-method-fail.rs:3:1
|
||||||
|
|
|
||||||
|
LL | #[const_trait]
|
||||||
|
| ^^^^^^^^^^^^^^ required by this bound in `Plus::plus`
|
||||||
|
LL | pub trait Plus {
|
||||||
|
LL | fn plus(self, rhs: Self) -> Self;
|
||||||
|
| ---- required by a bound in this associated function
|
||||||
|
|
||||||
error: aborting due to 1 previous error; 1 warning emitted
|
error: aborting due to 1 previous error; 1 warning emitted
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,66 @@
|
||||||
|
error: const `impl` for trait `Add` which is not marked with `#[const_trait]`
|
||||||
|
--> $DIR/call-const-trait-method-pass.rs:7:12
|
||||||
|
|
|
||||||
|
LL | impl const std::ops::Add for Int {
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
|
||||||
|
= note: adding a non-const method body in the future would be a breaking change
|
||||||
|
|
||||||
|
error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]`
|
||||||
|
--> $DIR/call-const-trait-method-pass.rs:15:12
|
||||||
|
|
|
||||||
|
LL | impl const PartialEq for Int {
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
|
||||||
|
= note: adding a non-const method body in the future would be a breaking change
|
||||||
|
|
||||||
|
error[E0049]: method `plus` has 1 const parameter but its trait declaration has 0 const parameters
|
||||||
|
--> $DIR/call-const-trait-method-pass.rs:24:1
|
||||||
|
|
|
||||||
|
LL | #[const_trait]
|
||||||
|
| ^^^^^^^^^^^^^^ found 1 const parameter
|
||||||
|
LL | pub trait Plus {
|
||||||
|
LL | fn plus(self, rhs: Self) -> Self;
|
||||||
|
| - expected 0 const parameters
|
||||||
|
|
||||||
error[E0015]: cannot call non-const operator in constants
|
error[E0015]: cannot call non-const operator in constants
|
||||||
--> $DIR/call-const-trait-method-pass.rs:39:22
|
--> $DIR/call-const-trait-method-pass.rs:39:22
|
||||||
|
|
|
|
||||||
LL | const ADD_INT: Int = Int(1i32) + Int(2i32);
|
LL | const ADD_INT: Int = Int(1i32) + Int(2i32);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: impl defined here, but it is not `const`
|
|
||||||
--> $DIR/call-const-trait-method-pass.rs:7:1
|
|
||||||
|
|
|
||||||
LL | impl const std::ops::Add for Int {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
|
||||||
help: add `#![feature(effects)]` to the crate attributes to enable
|
help: add `#![feature(effects)]` to the crate attributes to enable
|
||||||
|
|
|
|
||||||
LL + #![feature(effects)]
|
LL + #![feature(effects)]
|
||||||
|
|
|
|
||||||
|
|
||||||
|
error[E0015]: cannot call non-const fn `<i32 as Plus>::plus` in constant functions
|
||||||
|
--> $DIR/call-const-trait-method-pass.rs:11:20
|
||||||
|
|
|
||||||
|
LL | Int(self.0.plus(rhs.0))
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||||
|
help: add `#![feature(effects)]` to the crate attributes to enable
|
||||||
|
|
|
||||||
|
LL + #![feature(effects)]
|
||||||
|
|
|
||||||
|
|
||||||
|
error[E0015]: cannot call non-const fn `<Int as PartialEq>::eq` in constant functions
|
||||||
|
--> $DIR/call-const-trait-method-pass.rs:20:15
|
||||||
|
|
|
||||||
|
LL | !self.eq(other)
|
||||||
|
| ^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||||
|
help: add `#![feature(effects)]` to the crate attributes to enable
|
||||||
|
|
|
||||||
|
LL + #![feature(effects)]
|
||||||
|
|
|
||||||
|
|
||||||
error[E0015]: cannot call non-const fn `<i32 as Plus>::plus` in constant functions
|
error[E0015]: cannot call non-const fn `<i32 as Plus>::plus` in constant functions
|
||||||
--> $DIR/call-const-trait-method-pass.rs:36:7
|
--> $DIR/call-const-trait-method-pass.rs:36:7
|
||||||
|
|
|
|
||||||
|
@ -27,6 +73,7 @@ help: add `#![feature(effects)]` to the crate attributes to enable
|
||||||
LL + #![feature(effects)]
|
LL + #![feature(effects)]
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 7 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0015`.
|
Some errors have detailed explanations: E0015, E0049.
|
||||||
|
For more information about an error, try `rustc --explain E0015`.
|
||||||
|
|
|
@ -4,5 +4,28 @@ error: `~const` can only be applied to `#[const_trait]` traits
|
||||||
LL | impl<T: ~const PartialEq> const MyPartialEq for T {
|
LL | impl<T: ~const PartialEq> const MyPartialEq for T {
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error[E0049]: method `eq` has 1 const parameter but its trait declaration has 0 const parameters
|
||||||
|
--> $DIR/call-generic-in-impl.rs:5:1
|
||||||
|
|
|
||||||
|
LL | #[const_trait]
|
||||||
|
| ^^^^^^^^^^^^^^ found 1 const parameter
|
||||||
|
LL | trait MyPartialEq {
|
||||||
|
LL | fn eq(&self, other: &Self) -> bool;
|
||||||
|
| - expected 0 const parameters
|
||||||
|
|
||||||
|
error[E0015]: cannot call non-const fn `<T as PartialEq>::eq` in constant functions
|
||||||
|
--> $DIR/call-generic-in-impl.rs:12:9
|
||||||
|
|
|
||||||
|
LL | PartialEq::eq(self, other)
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||||
|
help: add `#![feature(effects)]` to the crate attributes to enable
|
||||||
|
|
|
||||||
|
LL + #![feature(effects)]
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0015, E0049.
|
||||||
|
For more information about an error, try `rustc --explain E0015`.
|
||||||
|
|
|
@ -16,15 +16,6 @@ LL | impl const PartialEq for S {
|
||||||
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
|
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
|
||||||
= note: adding a non-const method body in the future would be a breaking change
|
= note: adding a non-const method body in the future would be a breaking change
|
||||||
|
|
||||||
error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates
|
|
||||||
--> $DIR/call-generic-method-chain.rs:10:6
|
|
||||||
|
|
|
||||||
LL | impl const PartialEq for S {
|
|
||||||
| ^^^^^ unconstrained const parameter
|
|
||||||
|
|
|
||||||
= note: expressions using a const parameter must map each value to a distinct output value
|
|
||||||
= note: proving the result of expressions other than the parameter are unique is not supported
|
|
||||||
|
|
||||||
error: `~const` can only be applied to `#[const_trait]` traits
|
error: `~const` can only be applied to `#[const_trait]` traits
|
||||||
--> $DIR/call-generic-method-chain.rs:19:32
|
--> $DIR/call-generic-method-chain.rs:19:32
|
||||||
|
|
|
|
||||||
|
@ -37,35 +28,5 @@ error: `~const` can only be applied to `#[const_trait]` traits
|
||||||
LL | const fn equals_self_wrapper<T: ~const PartialEq>(t: &T) -> bool {
|
LL | const fn equals_self_wrapper<T: ~const PartialEq>(t: &T) -> bool {
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error[E0284]: type annotations needed
|
error: aborting due to 3 previous errors; 1 warning emitted
|
||||||
--> $DIR/call-generic-method-chain.rs:27:22
|
|
||||||
|
|
|
||||||
LL | pub const EQ: bool = equals_self_wrapper(&S);
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^ cannot infer the value of the constant `_`
|
|
||||||
|
|
|
||||||
note: required for `S` to implement `PartialEq`
|
|
||||||
--> $DIR/call-generic-method-chain.rs:10:12
|
|
||||||
|
|
|
||||||
LL | impl const PartialEq for S {
|
|
||||||
| ----- ^^^^^^^^^ ^
|
|
||||||
| |
|
|
||||||
| unsatisfied trait bound introduced here
|
|
||||||
|
|
||||||
error[E0284]: type annotations needed
|
|
||||||
--> $DIR/call-generic-method-chain.rs:15:10
|
|
||||||
|
|
|
||||||
LL | !self.eq(other)
|
|
||||||
| ^^^^^^^^^^^^^^ cannot infer the value of the constant `_`
|
|
||||||
|
|
|
||||||
note: required for `S` to implement `PartialEq`
|
|
||||||
--> $DIR/call-generic-method-chain.rs:10:12
|
|
||||||
|
|
|
||||||
LL | impl const PartialEq for S {
|
|
||||||
| ----- ^^^^^^^^^ ^
|
|
||||||
| |
|
|
||||||
| unsatisfied trait bound introduced here
|
|
||||||
|
|
||||||
error: aborting due to 6 previous errors; 1 warning emitted
|
|
||||||
|
|
||||||
Some errors have detailed explanations: E0207, E0284.
|
|
||||||
For more information about an error, try `rustc --explain E0207`.
|
|
||||||
|
|
|
@ -16,15 +16,6 @@ LL | impl const PartialEq for S {
|
||||||
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
|
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
|
||||||
= note: adding a non-const method body in the future would be a breaking change
|
= note: adding a non-const method body in the future would be a breaking change
|
||||||
|
|
||||||
error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates
|
|
||||||
--> $DIR/call-generic-method-dup-bound.rs:8:6
|
|
||||||
|
|
|
||||||
LL | impl const PartialEq for S {
|
|
||||||
| ^^^^^ unconstrained const parameter
|
|
||||||
|
|
|
||||||
= note: expressions using a const parameter must map each value to a distinct output value
|
|
||||||
= note: proving the result of expressions other than the parameter are unique is not supported
|
|
||||||
|
|
||||||
error: `~const` can only be applied to `#[const_trait]` traits
|
error: `~const` can only be applied to `#[const_trait]` traits
|
||||||
--> $DIR/call-generic-method-dup-bound.rs:19:44
|
--> $DIR/call-generic-method-dup-bound.rs:19:44
|
||||||
|
|
|
|
||||||
|
@ -37,49 +28,5 @@ error: `~const` can only be applied to `#[const_trait]` traits
|
||||||
LL | const fn equals_self2<T: A + ~const PartialEq>(t: &T) -> bool {
|
LL | const fn equals_self2<T: A + ~const PartialEq>(t: &T) -> bool {
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error[E0284]: type annotations needed
|
error: aborting due to 3 previous errors; 1 warning emitted
|
||||||
--> $DIR/call-generic-method-dup-bound.rs:30:22
|
|
||||||
|
|
|
||||||
LL | pub const EQ: bool = equals_self(&S) && equals_self2(&S);
|
|
||||||
| ^^^^^^^^^^^^^^^ cannot infer the value of the constant `_`
|
|
||||||
|
|
|
||||||
note: required for `S` to implement `PartialEq`
|
|
||||||
--> $DIR/call-generic-method-dup-bound.rs:8:12
|
|
||||||
|
|
|
||||||
LL | impl const PartialEq for S {
|
|
||||||
| ----- ^^^^^^^^^ ^
|
|
||||||
| |
|
|
||||||
| unsatisfied trait bound introduced here
|
|
||||||
|
|
||||||
error[E0284]: type annotations needed
|
|
||||||
--> $DIR/call-generic-method-dup-bound.rs:30:41
|
|
||||||
|
|
|
||||||
LL | pub const EQ: bool = equals_self(&S) && equals_self2(&S);
|
|
||||||
| ^^^^^^^^^^^^^^^^ cannot infer the value of the constant `_`
|
|
||||||
|
|
|
||||||
note: required for `S` to implement `PartialEq`
|
|
||||||
--> $DIR/call-generic-method-dup-bound.rs:8:12
|
|
||||||
|
|
|
||||||
LL | impl const PartialEq for S {
|
|
||||||
| ----- ^^^^^^^^^ ^
|
|
||||||
| |
|
|
||||||
| unsatisfied trait bound introduced here
|
|
||||||
|
|
||||||
error[E0284]: type annotations needed
|
|
||||||
--> $DIR/call-generic-method-dup-bound.rs:13:10
|
|
||||||
|
|
|
||||||
LL | !self.eq(other)
|
|
||||||
| ^^^^^^^^^^^^^^ cannot infer the value of the constant `_`
|
|
||||||
|
|
|
||||||
note: required for `S` to implement `PartialEq`
|
|
||||||
--> $DIR/call-generic-method-dup-bound.rs:8:12
|
|
||||||
|
|
|
||||||
LL | impl const PartialEq for S {
|
|
||||||
| ----- ^^^^^^^^^ ^
|
|
||||||
| |
|
|
||||||
| unsatisfied trait bound introduced here
|
|
||||||
|
|
||||||
error: aborting due to 7 previous errors; 1 warning emitted
|
|
||||||
|
|
||||||
Some errors have detailed explanations: E0207, E0284.
|
|
||||||
For more information about an error, try `rustc --explain E0207`.
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ const fn equals_self<T: ~const Foo>(t: &T) -> bool {
|
||||||
// it not using the impl.
|
// it not using the impl.
|
||||||
|
|
||||||
pub const EQ: bool = equals_self(&S);
|
pub const EQ: bool = equals_self(&S);
|
||||||
//~^ ERROR: the trait bound `S: const Foo` is not satisfied
|
//~^ ERROR: the trait bound `Runtime: const Compat` is not satisfied
|
||||||
|
// FIXME(effects) diagnostic
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -7,15 +7,15 @@ LL | #![feature(const_trait_impl, effects)]
|
||||||
= note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
|
= note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
|
||||||
= note: `#[warn(incomplete_features)]` on by default
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
error[E0277]: the trait bound `S: const Foo` is not satisfied
|
error[E0277]: the trait bound `Runtime: const Compat` is not satisfied
|
||||||
--> $DIR/call-generic-method-nonconst.rs:23:34
|
--> $DIR/call-generic-method-nonconst.rs:23:34
|
||||||
|
|
|
|
||||||
LL | pub const EQ: bool = equals_self(&S);
|
LL | pub const EQ: bool = equals_self(&S);
|
||||||
| ----------- ^^ the trait `const Foo` is not implemented for `S`
|
| ----------- ^^ the trait `const Compat` is not implemented for `Runtime`
|
||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
|
|
|
||||||
= help: the trait `Foo` is implemented for `S`
|
= help: the trait `Compat` is implemented for `Runtime`
|
||||||
note: required by a bound in `equals_self`
|
note: required by a bound in `equals_self`
|
||||||
--> $DIR/call-generic-method-nonconst.rs:16:25
|
--> $DIR/call-generic-method-nonconst.rs:16:25
|
||||||
|
|
|
|
||||||
|
|
|
@ -16,50 +16,11 @@ LL | impl const PartialEq for S {
|
||||||
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
|
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
|
||||||
= note: adding a non-const method body in the future would be a breaking change
|
= note: adding a non-const method body in the future would be a breaking change
|
||||||
|
|
||||||
error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates
|
|
||||||
--> $DIR/call-generic-method-pass.rs:10:6
|
|
||||||
|
|
|
||||||
LL | impl const PartialEq for S {
|
|
||||||
| ^^^^^ unconstrained const parameter
|
|
||||||
|
|
|
||||||
= note: expressions using a const parameter must map each value to a distinct output value
|
|
||||||
= note: proving the result of expressions other than the parameter are unique is not supported
|
|
||||||
|
|
||||||
error: `~const` can only be applied to `#[const_trait]` traits
|
error: `~const` can only be applied to `#[const_trait]` traits
|
||||||
--> $DIR/call-generic-method-pass.rs:19:32
|
--> $DIR/call-generic-method-pass.rs:19:32
|
||||||
|
|
|
|
||||||
LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
|
LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
error[E0284]: type annotations needed
|
error: aborting due to 2 previous errors; 1 warning emitted
|
||||||
--> $DIR/call-generic-method-pass.rs:23:22
|
|
||||||
|
|
|
||||||
LL | pub const EQ: bool = equals_self(&S);
|
|
||||||
| ^^^^^^^^^^^^^^^ cannot infer the value of the constant `_`
|
|
||||||
|
|
|
||||||
note: required for `S` to implement `PartialEq`
|
|
||||||
--> $DIR/call-generic-method-pass.rs:10:12
|
|
||||||
|
|
|
||||||
LL | impl const PartialEq for S {
|
|
||||||
| ----- ^^^^^^^^^ ^
|
|
||||||
| |
|
|
||||||
| unsatisfied trait bound introduced here
|
|
||||||
|
|
||||||
error[E0284]: type annotations needed
|
|
||||||
--> $DIR/call-generic-method-pass.rs:15:10
|
|
||||||
|
|
|
||||||
LL | !self.eq(other)
|
|
||||||
| ^^^^^^^^^^^^^^ cannot infer the value of the constant `_`
|
|
||||||
|
|
|
||||||
note: required for `S` to implement `PartialEq`
|
|
||||||
--> $DIR/call-generic-method-pass.rs:10:12
|
|
||||||
|
|
|
||||||
LL | impl const PartialEq for S {
|
|
||||||
| ----- ^^^^^^^^^ ^
|
|
||||||
| |
|
|
||||||
| unsatisfied trait bound introduced here
|
|
||||||
|
|
||||||
error: aborting due to 5 previous errors; 1 warning emitted
|
|
||||||
|
|
||||||
Some errors have detailed explanations: E0207, E0284.
|
|
||||||
For more information about an error, try `rustc --explain E0207`.
|
|
||||||
|
|
|
@ -1,3 +1,21 @@
|
||||||
|
error: const `impl` for trait `Add` which is not marked with `#[const_trait]`
|
||||||
|
--> $DIR/const-and-non-const-impl.rs:7:12
|
||||||
|
|
|
||||||
|
LL | impl const std::ops::Add for i32 {
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
|
||||||
|
= note: adding a non-const method body in the future would be a breaking change
|
||||||
|
|
||||||
|
error: const `impl` for trait `Add` which is not marked with `#[const_trait]`
|
||||||
|
--> $DIR/const-and-non-const-impl.rs:23:12
|
||||||
|
|
|
||||||
|
LL | impl const std::ops::Add for Int {
|
||||||
|
| ^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
|
||||||
|
= note: adding a non-const method body in the future would be a breaking change
|
||||||
|
|
||||||
error[E0119]: conflicting implementations of trait `Add` for type `Int`
|
error[E0119]: conflicting implementations of trait `Add` for type `Int`
|
||||||
--> $DIR/const-and-non-const-impl.rs:23:1
|
--> $DIR/const-and-non-const-impl.rs:23:1
|
||||||
|
|
|
|
||||||
|
@ -19,7 +37,7 @@ LL | impl const std::ops::Add for i32 {
|
||||||
|
|
|
|
||||||
= note: define and implement a trait or new type instead
|
= note: define and implement a trait or new type instead
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0117, E0119.
|
Some errors have detailed explanations: E0117, E0119.
|
||||||
For more information about an error, try `rustc --explain E0117`.
|
For more information about an error, try `rustc --explain E0117`.
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#![feature(const_trait_impl)]
|
#![allow(incomplete_features)]
|
||||||
|
#![feature(const_trait_impl, effects)]
|
||||||
|
|
||||||
#[const_trait]
|
#[const_trait]
|
||||||
trait MyTrait {
|
trait MyTrait {
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
error: `~const` is not allowed here
|
error: `~const` is not allowed here
|
||||||
--> $DIR/const-bound-on-not-const-associated-fn.rs:9:40
|
--> $DIR/const-bound-on-not-const-associated-fn.rs:10:40
|
||||||
|
|
|
|
||||||
LL | fn do_something_else() where Self: ~const MyTrait;
|
LL | fn do_something_else() where Self: ~const MyTrait;
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
|
||||||
note: this function is not `const`, so it cannot have `~const` trait bounds
|
note: this function is not `const`, so it cannot have `~const` trait bounds
|
||||||
--> $DIR/const-bound-on-not-const-associated-fn.rs:9:8
|
--> $DIR/const-bound-on-not-const-associated-fn.rs:10:8
|
||||||
|
|
|
|
||||||
LL | fn do_something_else() where Self: ~const MyTrait;
|
LL | fn do_something_else() where Self: ~const MyTrait;
|
||||||
| ^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `~const` is not allowed here
|
error: `~const` is not allowed here
|
||||||
--> $DIR/const-bound-on-not-const-associated-fn.rs:20:32
|
--> $DIR/const-bound-on-not-const-associated-fn.rs:21:32
|
||||||
|
|
|
|
||||||
LL | pub fn foo(&self) where T: ~const MyTrait {
|
LL | pub fn foo(&self) where T: ~const MyTrait {
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
|
||||||
note: this function is not `const`, so it cannot have `~const` trait bounds
|
note: this function is not `const`, so it cannot have `~const` trait bounds
|
||||||
--> $DIR/const-bound-on-not-const-associated-fn.rs:20:12
|
--> $DIR/const-bound-on-not-const-associated-fn.rs:21:12
|
||||||
|
|
|
|
||||||
LL | pub fn foo(&self) where T: ~const MyTrait {
|
LL | pub fn foo(&self) where T: ~const MyTrait {
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters
|
||||||
|
--> $DIR/const-closure-trait-method-fail.rs:5:1
|
||||||
|
|
|
||||||
|
LL | #[const_trait]
|
||||||
|
| ^^^^^^^^^^^^^^ found 1 const parameter
|
||||||
|
LL | trait Tr {
|
||||||
|
LL | fn a(self) -> i32;
|
||||||
|
| - expected 0 const parameters
|
||||||
|
|
||||||
error: `~const` can only be applied to `#[const_trait]` traits
|
error: `~const` can only be applied to `#[const_trait]` traits
|
||||||
--> $DIR/const-closure-trait-method-fail.rs:14:39
|
--> $DIR/const-closure-trait-method-fail.rs:14:39
|
||||||
|
|
|
|
||||||
|
@ -20,6 +29,7 @@ help: add `#![feature(effects)]` to the crate attributes to enable
|
||||||
LL + #![feature(effects)]
|
LL + #![feature(effects)]
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0015`.
|
Some errors have detailed explanations: E0015, E0049.
|
||||||
|
For more information about an error, try `rustc --explain E0015`.
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
error[E0049]: method `a` has 1 const parameter but its trait declaration has 0 const parameters
|
||||||
|
--> $DIR/const-closure-trait-method.rs:5:1
|
||||||
|
|
|
||||||
|
LL | #[const_trait]
|
||||||
|
| ^^^^^^^^^^^^^^ found 1 const parameter
|
||||||
|
LL | trait Tr {
|
||||||
|
LL | fn a(self) -> i32;
|
||||||
|
| - expected 0 const parameters
|
||||||
|
|
||||||
error: `~const` can only be applied to `#[const_trait]` traits
|
error: `~const` can only be applied to `#[const_trait]` traits
|
||||||
--> $DIR/const-closure-trait-method.rs:14:39
|
--> $DIR/const-closure-trait-method.rs:14:39
|
||||||
|
|
|
|
||||||
|
@ -20,6 +29,7 @@ help: add `#![feature(effects)]` to the crate attributes to enable
|
||||||
LL + #![feature(effects)]
|
LL + #![feature(effects)]
|
||||||
|
|
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0015`.
|
Some errors have detailed explanations: E0015, E0049.
|
||||||
|
For more information about an error, try `rustc --explain E0015`.
|
||||||
|
|
|
@ -7,13 +7,21 @@ LL | #![feature(const_trait_impl, effects)]
|
||||||
= note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
|
= note: see issue #102090 <https://github.com/rust-lang/rust/issues/102090> for more information
|
||||||
= note: `#[warn(incomplete_features)]` on by default
|
= note: `#[warn(incomplete_features)]` on by default
|
||||||
|
|
||||||
error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied
|
error[E0277]: the trait bound `Runtime: ~const Compat` is not satisfied
|
||||||
--> $DIR/const-default-method-bodies.rs:24:18
|
--> $DIR/const-default-method-bodies.rs:24:18
|
||||||
|
|
|
|
||||||
LL | NonConstImpl.a();
|
LL | NonConstImpl.a();
|
||||||
| ^ the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl`
|
| ^ the trait `~const Compat` is not implemented for `Runtime`
|
||||||
|
|
|
|
||||||
= help: the trait `ConstDefaultFn` is implemented for `NonConstImpl`
|
= help: the trait `Compat` is implemented for `Runtime`
|
||||||
|
note: required by a bound in `ConstDefaultFn::a`
|
||||||
|
--> $DIR/const-default-method-bodies.rs:3:1
|
||||||
|
|
|
||||||
|
LL | #[const_trait]
|
||||||
|
| ^^^^^^^^^^^^^^ required by this bound in `ConstDefaultFn::a`
|
||||||
|
...
|
||||||
|
LL | fn a(self) {
|
||||||
|
| - required by a bound in this associated function
|
||||||
|
|
||||||
error: aborting due to 1 previous error; 1 warning emitted
|
error: aborting due to 1 previous error; 1 warning emitted
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
error: const `impl` for trait `Drop` which is not marked with `#[const_trait]`
|
||||||
|
--> $DIR/const-drop-fail-2.rs:40:25
|
||||||
|
|
|
||||||
|
LL | impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
|
||||||
|
| ^^^^
|
||||||
|
|
|
||||||
|
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
|
||||||
|
= note: adding a non-const method body in the future would be a breaking change
|
||||||
|
|
||||||
error: `~const` can only be applied to `#[const_trait]` traits
|
error: `~const` can only be applied to `#[const_trait]` traits
|
||||||
--> $DIR/const-drop-fail-2.rs:21:26
|
--> $DIR/const-drop-fail-2.rs:21:26
|
||||||
|
|
|
|
||||||
|
@ -12,6 +21,19 @@ LL | const fn check<T: ~const Destruct>(_: T) {}
|
||||||
| |
|
| |
|
||||||
| the destructor for this type cannot be evaluated in constant functions
|
| the destructor for this type cannot be evaluated in constant functions
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error[E0015]: cannot call non-const fn `<T as A>::a` in constant functions
|
||||||
|
--> $DIR/const-drop-fail-2.rs:42:9
|
||||||
|
|
|
||||||
|
LL | T::a();
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
|
||||||
|
help: add `#![feature(effects)]` to the crate attributes to enable
|
||||||
|
|
|
||||||
|
LL + #![feature(effects)]
|
||||||
|
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0493`.
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0015, E0493.
|
||||||
|
For more information about an error, try `rustc --explain E0015`.
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
error: const `impl` for trait `Drop` which is not marked with `#[const_trait]`
|
||||||
|
--> $DIR/const-drop-fail.rs:20:12
|
||||||
|
|
|
||||||
|
LL | impl const Drop for ConstImplWithDropGlue {
|
||||||
|
| ^^^^
|
||||||
|
|
|
||||||
|
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
|
||||||
|
= note: adding a non-const method body in the future would be a breaking change
|
||||||
|
|
||||||
error: `~const` can only be applied to `#[const_trait]` traits
|
error: `~const` can only be applied to `#[const_trait]` traits
|
||||||
--> $DIR/const-drop-fail.rs:24:26
|
--> $DIR/const-drop-fail.rs:24:26
|
||||||
|
|
|
|
||||||
|
@ -38,8 +47,10 @@ LL | | }
|
||||||
error[E0080]: evaluation of constant value failed
|
error[E0080]: evaluation of constant value failed
|
||||||
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||||
|
|
|
|
||||||
= note: calling non-const function `<ConstImplWithDropGlue as Drop>::drop`
|
= note: calling non-const function `<NonTrivialDrop as Drop>::drop`
|
||||||
|
|
|
|
||||||
|
note: inside `std::ptr::drop_in_place::<NonTrivialDrop> - shim(Some(NonTrivialDrop))`
|
||||||
|
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||||
note: inside `std::ptr::drop_in_place::<ConstImplWithDropGlue> - shim(Some(ConstImplWithDropGlue))`
|
note: inside `std::ptr::drop_in_place::<ConstImplWithDropGlue> - shim(Some(ConstImplWithDropGlue))`
|
||||||
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
||||||
note: inside `check::<ConstImplWithDropGlue>`
|
note: inside `check::<ConstImplWithDropGlue>`
|
||||||
|
@ -60,7 +71,7 @@ LL | | }
|
||||||
| |_- in this macro invocation
|
| |_- in this macro invocation
|
||||||
= note: this error originates in the macro `check_all` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the macro `check_all` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0080, E0493.
|
Some errors have detailed explanations: E0080, E0493.
|
||||||
For more information about an error, try `rustc --explain E0080`.
|
For more information about an error, try `rustc --explain E0080`.
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue