Auto merge of #114545 - fee1-dead-contrib:lower-impl-effect, r=oli-obk

correctly lower `impl const` to bind to host effect param

r? `@oli-obk`
This commit is contained in:
bors 2023-08-08 19:23:41 +00:00
commit f88a8b71ce
64 changed files with 465 additions and 373 deletions

View File

@ -313,6 +313,16 @@ pub enum TraitBoundModifier {
MaybeConstMaybe,
}
impl TraitBoundModifier {
pub fn to_constness(self) -> Const {
match self {
// FIXME(effects) span
Self::MaybeConst => Const::Yes(DUMMY_SP),
_ => Const::No,
}
}
}
/// The AST represents all type param bounds as types.
/// `typeck::collect::compute_bounds` matches these against
/// the "special" built-in traits (see `middle::lang_items`) and

View File

@ -207,6 +207,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&sym.path,
ParamMode::Optional,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
hir::InlineAsmOperand::SymStatic { path, def_id }
} else {

View File

@ -100,6 +100,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ParamMode::Optional,
ParenthesizedGenericArgs::Err,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
));
let receiver = self.lower_expr(receiver);
let args =
@ -260,6 +261,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
path,
ParamMode::Optional,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
hir::ExprKind::Path(qpath)
}
@ -307,6 +309,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
&se.path,
ParamMode::Optional,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
)),
self.arena
.alloc_from_iter(se.fields.iter().map(|x| self.lower_expr_field(x))),
@ -1179,6 +1182,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
path,
ParamMode::Optional,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
// Destructure like a tuple struct.
let tuple_struct_pat = hir::PatKind::TupleStruct(
@ -1198,6 +1202,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
path,
ParamMode::Optional,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
// Destructure like a unit struct.
let unit_struct_pat = hir::PatKind::Path(qpath);
@ -1222,6 +1227,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
&se.path,
ParamMode::Optional,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
let fields_omitted = match &se.rest {
StructRest::Base(e) => {

View File

@ -90,6 +90,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()),
allow_gen_future,
generics_def_id_map: Default::default(),
host_param_id: None,
};
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
@ -144,8 +145,24 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
// This is used to track which lifetimes have already been defined,
// and which need to be replicated when lowering an async fn.
if let hir::ItemKind::Impl(impl_) = parent_hir.node().expect_item().kind {
lctx.is_in_trait_impl = impl_.of_trait.is_some();
match parent_hir.node().expect_item().kind {
hir::ItemKind::Impl(impl_) => {
lctx.is_in_trait_impl = impl_.of_trait.is_some();
}
hir::ItemKind::Trait(_, _, generics, _, _) if lctx.tcx.features().effects => {
lctx.host_param_id = generics
.params
.iter()
.find(|param| {
parent_hir
.attrs
.get(param.hir_id.local_id)
.iter()
.any(|attr| attr.has_name(sym::rustc_host))
})
.map(|param| param.def_id);
}
_ => {}
}
match ctxt {
@ -389,6 +406,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_generics(ast_generics, *constness, id, &itctx, |this| {
let trait_ref = trait_ref.as_ref().map(|trait_ref| {
this.lower_trait_ref(
*constness,
trait_ref,
&ImplTraitContext::Disallowed(ImplTraitPosition::Trait),
)
@ -419,7 +437,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
polarity,
defaultness,
defaultness_span,
constness: self.lower_constness(*constness),
generics,
of_trait: trait_ref,
self_ty: lowered_ty,
@ -1363,6 +1380,29 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}
// Desugar `~const` bound in generics into an additional `const host: bool` param
// 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
let host_param_parts = if let Const::Yes(span) = constness && self.tcx.features().effects {
if let Some(param) = generics.params.iter().find(|x| {
x.attrs.iter().any(|x| x.has_name(sym::rustc_host))
}) {
// user has manually specified a `rustc_host` param, in this case, we set
// the param id so that lowering logic can use that. But we don't create
// another host param, so this gives `None`.
self.host_param_id = Some(self.local_def_id(param.id));
None
} else {
let param_node_id = self.next_node_id();
let hir_id = self.next_id();
let def_id = self.create_def(self.local_def_id(parent_node_id), param_node_id, DefPathData::TypeNs(sym::host), span);
self.host_param_id = Some(def_id);
Some((span, hir_id, def_id))
}
} else {
None
};
let mut predicates: SmallVec<[hir::WherePredicate<'hir>; 4]> = SmallVec::new();
predicates.extend(generics.params.iter().filter_map(|param| {
self.lower_generic_bound_predicate(
@ -1410,22 +1450,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
let impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds);
predicates.extend(impl_trait_bounds.into_iter());
// Desugar `~const` bound in generics into an additional `const host: bool` param
// if the effects feature is enabled.
if let Const::Yes(span) = constness && self.tcx.features().effects
// Do not add host param if it already has it (manually specified)
&& !params.iter().any(|x| {
self.attrs.get(&x.hir_id.local_id).map_or(false, |attrs| {
attrs.iter().any(|x| x.has_name(sym::rustc_host))
})
})
{
let param_node_id = self.next_node_id();
if let Some((span, hir_id, def_id)) = host_param_parts {
let const_node_id = self.next_node_id();
let def_id = self.create_def(self.local_def_id(parent_node_id), param_node_id, DefPathData::TypeNs(sym::host), span);
let anon_const: LocalDefId = self.create_def(def_id, const_node_id, DefPathData::AnonConst, span);
let anon_const: LocalDefId =
self.create_def(def_id, const_node_id, DefPathData::AnonConst, span);
let hir_id = self.next_id();
let const_id = self.next_id();
let const_expr_id = self.next_id();
let bool_id = self.next_id();
@ -1435,14 +1464,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
let attr_id = self.tcx.sess.parse_sess.attr_id_generator.mk_attr_id();
let attrs = self.arena.alloc_from_iter([
Attribute {
kind: AttrKind::Normal(P(NormalAttr::from_ident(Ident::new(sym::rustc_host, span)))),
let attrs = self.arena.alloc_from_iter([Attribute {
kind: AttrKind::Normal(P(NormalAttr::from_ident(Ident::new(
sym::rustc_host,
span,
id: attr_id,
style: AttrStyle::Outer,
},
]);
)))),
span,
id: attr_id,
style: AttrStyle::Outer,
}]);
self.attrs.insert(hir_id.local_id, attrs);
let const_body = self.lower_body(|this| {
@ -1481,7 +1511,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
}),
)),
)),
default: Some(hir::AnonConst { def_id: anon_const, hir_id: const_id, body: const_body }),
default: Some(hir::AnonConst {
def_id: anon_const,
hir_id: const_id,
body: const_body,
}),
},
colon_span: None,
pure_wrt_drop: false,

View File

@ -142,6 +142,8 @@ struct LoweringContext<'a, 'hir> {
/// defined on the TAIT, so we have type Foo<'a1> = ... and we establish a mapping in this
/// field from the original parameter 'a to the new parameter 'a1.
generics_def_id_map: Vec<FxHashMap<LocalDefId, LocalDefId>>,
host_param_id: Option<LocalDefId>,
}
trait ResolverAstLoweringExt {
@ -1262,6 +1264,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
span: t.span
},
itctx,
ast::Const::No,
);
let bounds = this.arena.alloc_from_iter([bound]);
let lifetime_bound = this.elided_dyn_bound(t.span);
@ -1272,7 +1275,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
let id = self.lower_node_id(t.id);
let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx);
let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx, None);
self.ty_path(id, t.span, qpath)
}
@ -1356,10 +1359,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
this.arena.alloc_from_iter(bounds.iter().filter_map(|bound| match bound {
GenericBound::Trait(
ty,
TraitBoundModifier::None
modifier @ (TraitBoundModifier::None
| TraitBoundModifier::MaybeConst
| TraitBoundModifier::Negative,
) => Some(this.lower_poly_trait_ref(ty, itctx)),
| TraitBoundModifier::Negative),
) => {
Some(this.lower_poly_trait_ref(ty, itctx, modifier.to_constness()))
}
// `~const ?Bound` will cause an error during AST validation
// anyways, so treat it like `?Bound` as compilation proceeds.
GenericBound::Trait(
@ -1952,7 +1957,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
) -> hir::GenericBound<'hir> {
match tpb {
GenericBound::Trait(p, modifier) => hir::GenericBound::Trait(
self.lower_poly_trait_ref(p, itctx),
self.lower_poly_trait_ref(p, itctx, modifier.to_constness()),
self.lower_trait_bound_modifier(*modifier),
),
GenericBound::Outlives(lifetime) => {
@ -2095,8 +2100,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}
fn lower_trait_ref(&mut self, p: &TraitRef, itctx: &ImplTraitContext) -> hir::TraitRef<'hir> {
let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) {
fn lower_trait_ref(
&mut self,
constness: ast::Const,
p: &TraitRef,
itctx: &ImplTraitContext,
) -> hir::TraitRef<'hir> {
let path = match self.lower_qpath(
p.ref_id,
&None,
&p.path,
ParamMode::Explicit,
itctx,
Some(constness),
) {
hir::QPath::Resolved(None, path) => path,
qpath => panic!("lower_trait_ref: unexpected QPath `{qpath:?}`"),
};
@ -2108,10 +2125,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&mut self,
p: &PolyTraitRef,
itctx: &ImplTraitContext,
constness: ast::Const,
) -> hir::PolyTraitRef<'hir> {
let bound_generic_params =
self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params);
let trait_ref = self.lower_trait_ref(&p.trait_ref, itctx);
let trait_ref = self.lower_trait_ref(constness, &p.trait_ref, itctx);
hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) }
}
@ -2465,6 +2483,67 @@ struct GenericArgsCtor<'hir> {
}
impl<'hir> GenericArgsCtor<'hir> {
fn push_constness(&mut self, lcx: &mut LoweringContext<'_, 'hir>, constness: ast::Const) {
if !lcx.tcx.features().effects {
return;
}
// if bound is non-const, don't add host effect param
let ast::Const::Yes(span) = constness else { return };
let span = lcx.lower_span(span);
let id = lcx.next_node_id();
let hir_id = lcx.next_id();
let body = lcx.lower_body(|lcx| {
(
&[],
match constness {
ast::Const::Yes(_) => {
let hir_id = lcx.next_id();
let res =
Res::Def(DefKind::ConstParam, lcx.host_param_id.unwrap().to_def_id());
let expr_kind = 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)],
}),
));
lcx.expr(span, expr_kind)
}
ast::Const::No => lcx.expr(
span,
hir::ExprKind::Lit(
lcx.arena.alloc(hir::Lit { span, node: ast::LitKind::Bool(true) }),
),
),
},
)
});
let attr_id = lcx.tcx.sess.parse_sess.attr_id_generator.mk_attr_id();
let attr = lcx.arena.alloc(Attribute {
kind: AttrKind::Normal(P(NormalAttr::from_ident(Ident::new(sym::rustc_host, span)))),
span,
id: attr_id,
style: AttrStyle::Outer,
});
lcx.attrs.insert(hir_id.local_id, std::slice::from_ref(attr));
let def_id =
lcx.create_def(lcx.current_hir_id_owner.def_id, id, DefPathData::AnonConst, span);
lcx.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id)));
self.args.push(hir::GenericArg::Const(hir::ConstArg {
value: hir::AnonConst { def_id, hir_id, body },
span,
}))
}
fn is_empty(&self) -> bool {
self.args.is_empty()
&& self.bindings.is_empty()

View File

@ -38,6 +38,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
path,
ParamMode::Optional,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct");
break hir::PatKind::TupleStruct(qpath, pats, ddpos);
@ -54,6 +55,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
path,
ParamMode::Optional,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
break hir::PatKind::Path(qpath);
}
@ -64,6 +66,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
path,
ParamMode::Optional,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
let fs = self.arena.alloc_from_iter(fields.iter().map(|f| {

View File

@ -23,6 +23,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
p: &Path,
param_mode: ParamMode,
itctx: &ImplTraitContext,
// constness of the impl/bound if this is a trait path
constness: Option<ast::Const>,
) -> hir::QPath<'hir> {
let qself_position = qself.as_ref().map(|q| q.position);
let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx));
@ -73,6 +75,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
param_mode,
parenthesized_generic_args,
itctx,
// if this is the last segment, add constness to the trait path
if i == proj_start - 1 { constness } else { None },
)
},
)),
@ -119,6 +123,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
param_mode,
ParenthesizedGenericArgs::Err,
itctx,
None,
));
let qpath = hir::QPath::TypeRelative(ty, hir_segment);
@ -159,6 +164,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
param_mode,
ParenthesizedGenericArgs::Err,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
)
})),
span: self.lower_span(p.span),
@ -172,8 +178,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
param_mode: ParamMode,
parenthesized_generic_args: ParenthesizedGenericArgs,
itctx: &ImplTraitContext,
constness: Option<ast::Const>,
) -> hir::PathSegment<'hir> {
debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment,);
debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment);
let (mut generic_args, infer_args) = if let Some(generic_args) = segment.args.as_deref() {
match generic_args {
GenericArgs::AngleBracketed(data) => {
@ -231,6 +238,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
)
};
if let Some(constness) = constness {
generic_args.push_constness(self, constness);
}
let has_lifetimes =
generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));

View File

@ -40,7 +40,7 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
| hir::Node::AnonConst(_)
| hir::Node::ConstBlock(_)
| hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => hir::Constness::Const,
hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.constness,
hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }) => tcx.generics_of(def_id).host_effect_index.map_or(hir::Constness::NotConst, |_| hir::Constness::Const),
hir::Node::ForeignItem(hir::ForeignItem { kind: hir::ForeignItemKind::Fn(..), .. }) => {
// Intrinsics use `rustc_const_{un,}stable` attributes to indicate constness. All other
// foreign items cannot be evaluated at compile-time.

View File

@ -127,15 +127,8 @@ fn is_parent_const_stable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
let hir_id = tcx.local_def_id_to_hir_id(local_def_id);
let Some(parent) = tcx.hir().opt_parent_id(hir_id) else { return false };
let parent_def = tcx.hir().get(parent);
if !matches!(
parent_def,
hir::Node::Item(hir::Item {
kind: hir::ItemKind::Impl(hir::Impl { constness: hir::Constness::Const, .. }),
..
})
) {
if !tcx.is_const_trait_impl_raw(parent.owner.def_id.to_def_id()) {
return false;
}

View File

@ -145,8 +145,11 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
let implsrc = selcx.select(&obligation);
if let Ok(Some(ImplSource::UserDefined(data))) = implsrc {
let span = tcx.def_span(data.impl_def_id);
err.subdiagnostic(errors::NonConstImplNote { span });
// FIXME(effects) revisit this
if !tcx.is_const_trait_impl_raw(data.impl_def_id) {
let span = tcx.def_span(data.impl_def_id);
err.subdiagnostic(errors::NonConstImplNote { span });
}
}
}
_ => {}

View File

@ -3359,7 +3359,6 @@ pub struct Impl<'hir> {
// We do not put a `Span` in `Defaultness` because it breaks foreign crate metadata
// decoding as `Span`s cannot be decoded when a `Session` is not available.
pub defaultness_span: Option<Span>,
pub constness: Constness,
pub generics: &'hir Generics<'hir>,
/// The trait being implemented, if any.

View File

@ -522,7 +522,6 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
unsafety: _,
defaultness: _,
polarity: _,
constness: _,
defaultness_span: _,
ref generics,
ref of_trait,

View File

@ -532,6 +532,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
if let Err(guar) = ty.error_reported() {
return ty::Const::new_error(tcx, guar, ty).into();
}
// FIXME(effects) see if we should special case effect params here
if !infer_args && has_default {
tcx.const_param_default(param.def_id)
.instantiate(tcx, args.unwrap())
@ -659,7 +660,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&self,
trait_ref: &hir::TraitRef<'_>,
self_ty: Ty<'tcx>,
constness: ty::BoundConstness,
) -> ty::TraitRef<'tcx> {
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter(), |_| {});
@ -669,7 +669,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self_ty,
trait_ref.path.segments.last().unwrap(),
true,
constness,
ty::BoundConstness::NotConst,
)
}
@ -849,6 +849,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self_ty: Ty<'tcx>,
trait_segment: &hir::PathSegment<'_>,
is_impl: bool,
// FIXME(effects) move all host param things in astconv to hir lowering
constness: ty::BoundConstness,
) -> ty::TraitRef<'tcx> {
let (generic_args, _) = self.create_args_for_ast_trait_ref(
@ -2714,11 +2715,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
};
let i = hir.get_parent(fn_hir_id).expect_item().expect_impl();
let trait_ref = self.instantiate_mono_trait_ref(
i.of_trait.as_ref()?,
self.ast_ty_to_ty(i.self_ty),
ty::BoundConstness::NotConst,
);
let trait_ref =
self.instantiate_mono_trait_ref(i.of_trait.as_ref()?, self.ast_ty_to_ty(i.self_ty));
let assoc = tcx.associated_items(trait_ref.def_id).find_by_name_and_kind(
tcx,

View File

@ -1359,38 +1359,60 @@ fn impl_trait_ref(
.as_ref()
.map(|ast_trait_ref| {
let selfty = tcx.type_of(def_id).instantiate_identity();
icx.astconv().instantiate_mono_trait_ref(
ast_trait_ref,
selfty,
check_impl_constness(tcx, impl_.constness, ast_trait_ref),
)
if let Some(ErrorGuaranteed { .. }) = check_impl_constness(
tcx,
tcx.is_const_trait_impl_raw(def_id.to_def_id()),
&ast_trait_ref,
) {
// we have a const impl, but for a trait without `#[const_trait]`, so
// without the host param. If we continue with the HIR trait ref, we get
// ICEs for generic arg count mismatch. We do a little HIR editing to
// make astconv happy.
let mut path_segments = ast_trait_ref.path.segments.to_vec();
let last_segment = path_segments.len() - 1;
let mut args = path_segments[last_segment].args().clone();
let last_arg = args.args.len() - 1;
assert!(matches!(args.args[last_arg], hir::GenericArg::Const(anon_const) if tcx.has_attr(anon_const.value.def_id, sym::rustc_host)));
args.args = &args.args[..args.args.len() - 1];
path_segments[last_segment].args = Some(&args);
let path = hir::Path {
span: ast_trait_ref.path.span,
res: ast_trait_ref.path.res,
segments: &path_segments,
};
let trait_ref = hir::TraitRef { path: &path, hir_ref_id: ast_trait_ref.hir_ref_id };
icx.astconv().instantiate_mono_trait_ref(&trait_ref, selfty)
} else {
icx.astconv().instantiate_mono_trait_ref(&ast_trait_ref, selfty)
}
})
.map(ty::EarlyBinder::bind)
}
fn check_impl_constness(
tcx: TyCtxt<'_>,
constness: hir::Constness,
is_const: bool,
ast_trait_ref: &hir::TraitRef<'_>,
) -> ty::BoundConstness {
match constness {
hir::Constness::Const => {
if let Some(trait_def_id) = ast_trait_ref.trait_def_id() && !tcx.has_attr(trait_def_id, sym::const_trait) {
let trait_name = tcx.item_name(trait_def_id).to_string();
tcx.sess.emit_err(errors::ConstImplForNonConstTrait {
trait_ref_span: ast_trait_ref.path.span,
trait_name,
local_trait_span: trait_def_id.as_local().map(|_| tcx.def_span(trait_def_id).shrink_to_lo()),
marking: (),
adding: (),
});
ty::BoundConstness::NotConst
} else {
ty::BoundConstness::ConstIfConst
}
},
hir::Constness::NotConst => ty::BoundConstness::NotConst,
) -> Option<ErrorGuaranteed> {
if !is_const {
return None;
}
let trait_def_id = ast_trait_ref.trait_def_id()?;
if tcx.has_attr(trait_def_id, sym::const_trait) {
return None;
}
let trait_name = tcx.item_name(trait_def_id).to_string();
Some(tcx.sess.emit_err(errors::ConstImplForNonConstTrait {
trait_ref_span: ast_trait_ref.path.span,
trait_name,
local_trait_span:
trait_def_id.as_local().map(|_| tcx.def_span(trait_def_id).shrink_to_lo()),
marking: (),
adding: (),
}))
}
fn impl_polarity(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplPolarity {

View File

@ -320,7 +320,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
bug!("parent also has host effect param? index: {idx}, def: {def_id:?}");
}
host_effect_index = Some(parent_count + index as usize);
host_effect_index = Some(index as usize);
}
Some(ty::GenericParamDef {

View File

@ -578,6 +578,9 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
MissingTypesOrConsts { .. } => {
self.suggest_adding_type_and_const_args(err);
}
ExcessTypesOrConsts { .. } => {
// this can happen with `~const T` where T isn't a const_trait.
}
_ => unreachable!(),
}
}

View File

@ -626,7 +626,6 @@ impl<'a> State<'a> {
unsafety,
polarity,
defaultness,
constness,
defaultness_span: _,
generics,
ref of_trait,
@ -643,10 +642,6 @@ impl<'a> State<'a> {
self.space();
}
if constness == hir::Constness::Const {
self.word_nbsp("const");
}
if let hir::ImplPolarity::Negative(_) = polarity {
self.word("!");
}

View File

@ -767,9 +767,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
let tcx = self.tcx;
if !tcx.features().effects || tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you {
return;
}
// fast-reject if callee doesn't have the host effect param (non-const)
let generics = tcx.generics_of(callee_did);
let Some(host_effect_index) = generics.host_effect_index else { return };
// if the callee does have the param, we need to equate the param to some const
// value no matter whether the effects feature is enabled in the local crate,
// because inference will fail if we don't.
let mut host_always_on =
!tcx.features().effects || tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you;
// Compute the constness required by the context.
let context = tcx.hir().enclosing_body_owner(call_expr_hir);
@ -780,10 +786,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if tcx.has_attr(context.to_def_id(), sym::rustc_do_not_const_check) {
trace!("do not const check this context");
return;
host_always_on = true;
}
let effect = match const_context {
_ if host_always_on => tcx.consts.true_,
Some(hir::ConstContext::Static(_) | hir::ConstContext::Const) => tcx.consts.false_,
Some(hir::ConstContext::ConstFn) => {
let args = ty::GenericArgs::identity_for_item(tcx, context);
@ -792,21 +799,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None => tcx.consts.true_,
};
let generics = tcx.generics_of(callee_did);
trace!(?effect, ?generics, ?callee_args);
if let Some(idx) = generics.host_effect_index {
let param = callee_args.const_at(idx);
let cause = self.misc(span);
match self.at(&cause, self.param_env).eq(infer::DefineOpaqueTypes::No, effect, param) {
Ok(infer::InferOk { obligations, value: () }) => {
self.register_predicates(obligations);
}
Err(e) => {
// FIXME(effects): better diagnostic
self.err_ctxt().report_mismatched_consts(&cause, effect, param, e).emit();
}
let param = callee_args.const_at(host_effect_index);
let cause = self.misc(span);
match self.at(&cause, self.param_env).eq(infer::DefineOpaqueTypes::No, effect, param) {
Ok(infer::InferOk { obligations, value: () }) => {
self.register_predicates(obligations);
}
Err(e) => {
// FIXME(effects): better diagnostic
self.err_ctxt().report_mismatched_consts(&cause, effect, param, e).emit();
}
}
}

View File

@ -1349,7 +1349,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
GenericParamDefKind::Const { has_default } => {
if !infer_args && has_default {
if !infer_args
&& has_default
&& !tcx.has_attr(param.def_id, sym::rustc_host)
{
tcx.const_param_default(param.def_id)
.instantiate(tcx, args.unwrap())
.into()

View File

@ -2041,9 +2041,9 @@ impl<'tcx> TyCtxt<'tcx> {
matches!(
node,
hir::Node::Item(hir::Item {
kind: hir::ItemKind::Impl(hir::Impl { constness: hir::Constness::Const, .. }),
kind: hir::ItemKind::Impl(hir::Impl { generics, .. }),
..
})
}) if generics.params.iter().any(|p| self.has_attr(p.def_id, sym::rustc_host))
)
}

View File

@ -2841,6 +2841,11 @@ define_print_and_forward_display! {
ty::TraitPredicate<'tcx> {
p!(print(self.trait_ref.self_ty()), ": ");
if let Some(idx) = cx.tcx().generics_of(self.trait_ref.def_id).host_effect_index {
if self.trait_ref.args.const_at(idx) != cx.tcx().consts.true_ {
p!("~const ");
}
}
// FIXME(effects) print `~const` here
if let ty::ImplPolarity::Negative = self.polarity {
p!("!");

View File

@ -732,13 +732,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
// For implementations of traits, check the stability of each item
// individually as it's possible to have a stable trait with unstable
// items.
hir::ItemKind::Impl(hir::Impl {
of_trait: Some(ref t),
self_ty,
items,
constness,
..
}) => {
hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref t), self_ty, items, .. }) => {
let features = self.tcx.features();
if features.staged_api {
let attrs = self.tcx.hir().attrs(item.hir_id());
@ -769,7 +763,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
// `#![feature(const_trait_impl)]` is unstable, so any impl declared stable
// needs to have an error emitted.
if features.const_trait_impl
&& *constness == hir::Constness::Const
&& self.tcx.is_const_trait_impl_raw(item.owner_id.to_def_id())
&& const_stab.is_some_and(|(stab, _)| stab.is_const_stable())
{
self.tcx.sess.emit_err(errors::TraitImplConstStable { span: item.span });

View File

@ -3110,27 +3110,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
) -> UnsatisfiedConst {
let unsatisfied_const = UnsatisfiedConst(false);
// FIXME(effects)
/* if trait_predicate.is_const_if_const() {
let non_const_predicate = trait_ref.without_const();
let non_const_obligation = Obligation {
cause: obligation.cause.clone(),
param_env: obligation.param_env,
predicate: non_const_predicate.to_predicate(self.tcx),
recursion_depth: obligation.recursion_depth,
};
if self.predicate_may_hold(&non_const_obligation) {
unsatisfied_const = UnsatisfiedConst(true);
err.span_note(
span,
format!(
"the trait `{}` is implemented for `{}`, \
but that implementation is not `const`",
non_const_predicate.print_modifiers_and_trait_path(),
trait_ref.skip_binder().self_ty(),
),
);
}
} */
unsatisfied_const
}

View File

@ -1,6 +1,6 @@
// build-pass
#![feature(const_trait_impl)]
#![feature(const_trait_impl, effects)]
#[const_trait]
trait Func<T> {

View File

@ -1,11 +1,39 @@
error: const `impl` for trait `Add` which is not marked with `#[const_trait]`
--> $DIR/unify-op-with-fn-call.rs:10:12
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
|
LL | impl const std::ops::Add for Foo {
| ^^^^^^^^^^^^^
LL | struct Evaluatable<const N: Foo>;
| ^^^
|
help: add `#[derive(ConstParamTy)]` to the struct
|
LL + #[derive(ConstParamTy)]
LL | struct Foo(u8);
|
= 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 previous error
error[E0741]: `Foo` must implement `ConstParamTy` to be used as the type of a const generic parameter
--> $DIR/unify-op-with-fn-call.rs:20:17
|
LL | fn foo<const N: Foo>(a: Evaluatable<{ N + N }>) {
| ^^^
|
help: add `#[derive(ConstParamTy)]` to the struct
|
LL + #[derive(ConstParamTy)]
LL | struct Foo(u8);
|
error[E0741]: `Foo` must implement `ConstParamTy` to be used as the type of a const generic parameter
--> $DIR/unify-op-with-fn-call.rs:24:17
|
LL | fn bar<const N: Foo>() {}
| ^^^
|
help: add `#[derive(ConstParamTy)]` to the struct
|
LL + #[derive(ConstParamTy)]
LL | struct Foo(u8);
|
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0741`.

View File

@ -1,20 +1,29 @@
error: const `impl` for trait `FromResidual` which is not marked with `#[const_trait]`
--> $DIR/const-try.rs:15:12
error[E0015]: `?` cannot determine the branch of `TryMe` in constant functions
--> $DIR/const-try.rs:33:5
|
LL | impl const FromResidual<Error> for TryMe {
| ^^^^^^^^^^^^^^^^^^^
LL | 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: const `impl` for trait `Try` which is not marked with `#[const_trait]`
--> $DIR/const-try.rs:21:12
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
error[E0015]: `?` cannot convert from residual of `TryMe` in constant functions
--> $DIR/const-try.rs:33:5
|
= 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
LL | TryMe?;
| ^^^^^^
|
note: impl defined here, but it is not `const`
--> $DIR/const-try.rs:15:1
|
LL | impl const FromResidual<Error> for TryMe {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0015`.

View File

@ -2,7 +2,7 @@
#![crate_type = "lib"]
#![feature(staged_api)]
#![feature(const_trait_impl)]
#![feature(const_trait_impl, effects)]
#![stable(feature = "foo", since = "1.0.0")]
#[stable(feature = "potato", since = "1.27.0")]

View File

@ -7,5 +7,15 @@ LL | impl const Default for Data {
= 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 previous error
error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates
--> $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
For more information about this error, try `rustc --explain E0207`.

View File

@ -1,4 +1,4 @@
#![feature(const_trait_impl)]
#![feature(const_trait_impl, effects)]
#[const_trait]
pub trait MyTrait {

View File

@ -1,4 +1,4 @@
#![feature(const_trait_impl)]
#![feature(const_trait_impl, effects)]
#![feature(staged_api)]
#![stable(feature = "rust1", since = "1.0.0")]

View File

@ -1,4 +1,4 @@
#![feature(const_trait_impl)]
#![feature(const_trait_impl, effects)]
#[const_trait]
pub trait Plus {
@ -23,7 +23,7 @@ pub const fn add_i32(a: i32, b: i32) -> i32 {
pub const fn add_u32(a: u32, b: u32) -> u32 {
a.plus(b)
//~^ ERROR cannot call
//~^ ERROR the trait bound
}
fn main() {}

View File

@ -1,11 +1,11 @@
error[E0015]: cannot call non-const fn `<u32 as Plus>::plus` in constant functions
error[E0277]: the trait bound `u32: ~const Plus` is not satisfied
--> $DIR/call-const-trait-method-fail.rs:25:7
|
LL | a.plus(b)
| ^^^^^^^
| ^^^^ the trait `Plus` is not implemented for `u32`
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
= help: the trait `Plus` is implemented for `u32`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0015`.
For more information about this error, try `rustc --explain E0277`.

View File

@ -1,20 +1,24 @@
error: const `impl` for trait `Add` which is not marked with `#[const_trait]`
--> $DIR/call-const-trait-method-pass.rs:7:12
error[E0015]: cannot call non-const fn `<i32 as Plus>::plus` in constant functions
--> $DIR/call-const-trait-method-pass.rs:36:7
|
LL | a.plus(b)
| ^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const operator in constants
--> $DIR/call-const-trait-method-pass.rs:39:22
|
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: 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0015`.

View File

@ -1,12 +1,3 @@
error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]`
--> $DIR/call-generic-method-chain.rs:9:12
|
LL | impl const PartialEq for S {
| ^^^^^^^^^
|
= 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
--> $DIR/call-generic-method-chain.rs:18:32
|
@ -19,5 +10,5 @@ error: ~const can only be applied to `#[const_trait]` traits
LL | const fn equals_self_wrapper<T: ~const PartialEq>(t: &T) -> bool {
| ^^^^^^^^^
error: aborting due to 3 previous errors
error: aborting due to 2 previous errors

View File

@ -1,12 +1,3 @@
error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]`
--> $DIR/call-generic-method-dup-bound.rs:7:12
|
LL | impl const PartialEq for S {
| ^^^^^^^^^
|
= 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
--> $DIR/call-generic-method-dup-bound.rs:18:44
|
@ -19,5 +10,5 @@ error: ~const can only be applied to `#[const_trait]` traits
LL | const fn equals_self2<T: A + ~const PartialEq>(t: &T) -> bool {
| ^^^^^^^^^
error: aborting due to 3 previous errors
error: aborting due to 2 previous errors

View File

@ -1,17 +1,8 @@
error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]`
--> $DIR/call-generic-method-pass.rs:9:12
|
LL | impl const PartialEq for S {
| ^^^^^^^^^
|
= 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
--> $DIR/call-generic-method-pass.rs:18:32
|
LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
| ^^^^^^^^^
error: aborting due to 2 previous errors
error: aborting due to previous error

View File

@ -1,20 +1,25 @@
error: const `impl` for trait `Add` which is not marked with `#[const_trait]`
--> $DIR/const-and-non-const-impl.rs:7:12
error[E0117]: only traits defined in the current crate can be implemented for primitive types
--> $DIR/const-and-non-const-impl.rs:7:1
|
LL | impl const std::ops::Add for i32 {
| ^^^^^^^^^^^^^
| ^^^^^^^^^^^-------------^^^^^---
| | | |
| | | `i32` is not defined in the current crate
| | `i32` is not defined in the current crate
| impl doesn't use only types from inside the current crate
|
= 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: define and implement a trait or new type instead
error: const `impl` for trait `Add` which is not marked with `#[const_trait]`
--> $DIR/const-and-non-const-impl.rs:23:12
error[E0119]: conflicting implementations of trait `Add` for type `Int`
--> $DIR/const-and-non-const-impl.rs:23:1
|
LL | impl std::ops::Add for Int {
| -------------------------- first implementation here
...
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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Int`
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0117, E0119.
For more information about an error, try `rustc --explain E0117`.

View File

@ -1,4 +1,4 @@
#![feature(const_trait_impl)]
#![feature(const_trait_impl, effects)]
struct S;
#[const_trait]

View File

@ -1,4 +1,4 @@
#![feature(const_trait_impl)]
#![feature(const_trait_impl, effects)]
#[const_trait]
trait ConstDefaultFn: Sized {
@ -22,7 +22,7 @@ impl const ConstDefaultFn for ConstImpl {
const fn test() {
NonConstImpl.a();
//~^ ERROR cannot call
//~^ ERROR the trait bound
ConstImpl.a();
}

View File

@ -1,11 +1,11 @@
error[E0015]: cannot call non-const fn `<NonConstImpl as ConstDefaultFn>::a` in constant functions
error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied
--> $DIR/const-default-method-bodies.rs:24:18
|
LL | NonConstImpl.a();
| ^^^
| ^ the trait `ConstDefaultFn` is not implemented for `NonConstImpl`
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
= help: the trait `ConstDefaultFn` is implemented for `NonConstImpl`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0015`.
For more information about this error, try `rustc --explain E0277`.

View File

@ -18,6 +18,10 @@ trait A { fn a() { } }
impl A for NonTrivialDrop {}
const fn check<T: ~const Destruct>(_: T) {}
/* FIXME(effects)
struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
@ -26,11 +30,10 @@ impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
}
}
const fn check<T: ~const Destruct>(_: T) {}
const _: () = check::<ConstDropImplWithBounds<NonTrivialDrop>>(
ConstDropImplWithBounds(PhantomData)
);
*/
struct ConstDropImplWithNonConstBounds<T: A>(PhantomData<T>);

View File

@ -1,28 +1,11 @@
error[E0015]: cannot call non-const fn `<T as A>::a` in constant functions
--> $DIR/const-drop-fail-2.rs:25:9
|
LL | T::a();
| ^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0493]: destructor of `T` cannot be evaluated at compile-time
--> $DIR/const-drop-fail-2.rs:29:36
--> $DIR/const-drop-fail-2.rs:21:36
|
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^ - value is dropped here
| |
| the destructor for this type cannot be evaluated in constant functions
error[E0015]: cannot call non-const fn `<T as A>::a` in constant functions
--> $DIR/const-drop-fail-2.rs:39:9
|
LL | T::a();
| ^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0015, E0493.
For more information about an error, try `rustc --explain E0015`.
For more information about this error, try `rustc --explain E0493`.

View File

@ -14,15 +14,6 @@ LL | let _ = S(&mut c);
| |
| the destructor for this type cannot be evaluated in constant functions
error[E0015]: cannot call non-const fn `<T as SomeTrait>::foo` in constant functions
--> $DIR/const-drop.rs:70:13
|
LL | T::foo();
| ^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to 2 previous errors
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0015, E0493.
For more information about an error, try `rustc --explain E0015`.
For more information about this error, try `rustc --explain E0493`.

View File

@ -14,15 +14,6 @@ LL | let _ = S(&mut c);
| |
| the destructor for this type cannot be evaluated in constant functions
error[E0015]: cannot call non-const fn `<T as SomeTrait>::foo` in constant functions
--> $DIR/const-drop.rs:70:13
|
LL | T::foo();
| ^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to 2 previous errors
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0015, E0493.
For more information about an error, try `rustc --explain E0015`.
For more information about this error, try `rustc --explain E0493`.

View File

@ -1,9 +1,11 @@
#![feature(const_trait_impl)]
// known-bug: #110395
#![feature(const_trait_impl, effects)]
pub trait A {}
//~^ HELP: mark `A` as const
// FIXME ~^ HELP: mark `A` as const
impl const A for () {}
//~^ ERROR: const `impl` for trait `A` which is not marked with `#[const_trait]`
// FIXME ~^ ERROR: const `impl` for trait `A` which is not marked with `#[const_trait]`
fn main() {}

View File

@ -1,5 +1,5 @@
error: const `impl` for trait `A` which is not marked with `#[const_trait]`
--> $DIR/const-impl-requires-const-trait.rs:6:12
--> $DIR/const-impl-requires-const-trait.rs:8:12
|
LL | pub trait A {}
| - help: mark `A` as const: `#[const_trait]`

View File

@ -1,5 +1,4 @@
#[derive_const(Default)] //~ ERROR use of unstable library feature
//~^ ERROR not marked with `#[const_trait]`
pub struct S;
fn main() {}

View File

@ -6,16 +6,6 @@ LL | #[derive_const(Default)]
|
= help: add `#![feature(derive_const)]` to the crate attributes to enable
error: const `impl` for trait `Default` which is not marked with `#[const_trait]`
--> $DIR/derive-const-gate.rs:1:16
|
LL | #[derive_const(Default)]
| ^^^^^^^
|
= 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: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors
error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.

View File

@ -1,5 +1,5 @@
// known-bug: #110395
#![feature(derive_const)]
#![feature(derive_const, effects)]
pub struct A;

View File

@ -10,44 +10,6 @@ error[E0635]: unknown feature `const_default_impls`
LL | #![feature(const_trait_impl, const_cmp, const_default_impls, derive_const)]
| ^^^^^^^^^^^^^^^^^^^
error: const `impl` for trait `Default` which is not marked with `#[const_trait]`
--> $DIR/derive-const-use.rs:6:12
|
LL | impl const Default 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: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]`
--> $DIR/derive-const-use.rs:10:12
|
LL | impl const PartialEq 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: const `impl` for trait `Default` which is not marked with `#[const_trait]`
--> $DIR/derive-const-use.rs:14:16
|
LL | #[derive_const(Default, PartialEq)]
| ^^^^^^^
|
= 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: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]`
--> $DIR/derive-const-use.rs:14:25
|
LL | #[derive_const(Default, PartialEq)]
| ^^^^^^^^^
|
= 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: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 6 previous errors
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0635`.

View File

@ -1,13 +1,3 @@
error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]`
--> $DIR/derive-const-with-params.rs:6:16
|
LL | #[derive_const(PartialEq)]
| ^^^^^^^^^
|
= 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: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/derive-const-with-params.rs:6:16
|
@ -16,5 +6,5 @@ LL | #[derive_const(PartialEq)]
|
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors
error: aborting due to previous error

View File

@ -1,11 +1,11 @@
error[E0015]: cannot call non-const fn `<cross_crate::NonConst as cross_crate::MyTrait>::func` in constant functions
error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied
--> $DIR/cross-crate.rs:17:14
|
LL | NonConst.func();
| ^^^^^^
| ^^^^ the trait `cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
= help: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0015`.
For more information about this error, try `rustc --explain E0277`.

View File

@ -1,6 +1,6 @@
// revisions: stock gated stocknc gatednc
// [gated] check-pass
#![cfg_attr(any(gated, gatednc), feature(const_trait_impl))]
#![cfg_attr(any(gated, gatednc), feature(const_trait_impl, effects))]
// aux-build: cross-crate.rs
extern crate cross_crate;
@ -16,7 +16,7 @@ const fn const_context() {
#[cfg(any(stocknc, gatednc))]
NonConst.func();
//[stocknc]~^ ERROR: cannot call
//[gatednc]~^^ ERROR: cannot call
//[gatednc]~^^ ERROR: the trait bound
Const.func();
//[stock]~^ ERROR: cannot call
//[stocknc]~^^ ERROR: cannot call

View File

@ -1,4 +1,4 @@
error[E0277]: the trait bound `(): Tr` is not satisfied
error[E0277]: the trait bound `(): ~const Tr` is not satisfied
--> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12
|
LL | ().a()

View File

@ -1,5 +1,5 @@
// check-pass
#![feature(const_trait_impl, rustc_attrs)]
#![feature(const_trait_impl, rustc_attrs, effects)]
#[const_trait]
trait Foo {

View File

@ -7,7 +7,7 @@
// ensure we are passing in the correct host effect in always const contexts.
pub const fn hmm</* T, */ #[rustc_host] const host: bool = true>() -> usize {
pub const fn hmm<T, #[rustc_host] const host: bool = true>() -> usize {
if host {
1
} else {
@ -16,14 +16,12 @@ pub const fn hmm</* T, */ #[rustc_host] const host: bool = true>() -> usize {
}
const _: () = {
let x = hmm();
let x = hmm::<()>();
assert!(0 == x);
};
/* FIXME(effects)
pub const fn uwu(x: [u8; hmm::<()>()]) {
let [] = x;
}
*/
fn main() {}

View File

@ -1,11 +1,16 @@
error: const `impl` for trait `Add` which is not marked with `#[const_trait]`
--> $DIR/generic-bound.rs:16:15
error[E0015]: cannot call non-const operator in constant functions
--> $DIR/generic-bound.rs:25:5
|
LL | arg + arg
| ^^^^^^^^^
|
note: impl defined here, but it is not `const`
--> $DIR/generic-bound.rs:16:1
|
LL | impl<T> const std::ops::Add for S<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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to previous error
For more information about this error, try `rustc --explain E0015`.

View File

@ -1,6 +1,6 @@
// Regression test for #69615.
#![feature(const_trait_impl)]
#![feature(const_trait_impl, effects)]
#[const_trait]
pub trait MyTrait {

View File

@ -1,6 +1,6 @@
// Tests that specializing trait impls must be at least as const as the default impl.
#![feature(const_trait_impl)]
#![feature(const_trait_impl, effects)]
#![feature(min_specialization)]
#[const_trait]

View File

@ -1,4 +1,4 @@
#![feature(const_trait_impl, min_specialization, rustc_attrs)]
#![feature(const_trait_impl, effects, min_specialization, rustc_attrs)]
#[rustc_specialization_trait]
#[const_trait]

View File

@ -1,7 +1,7 @@
// revisions: stable unstable
#![cfg_attr(unstable, feature(unstable))] // The feature from the ./auxiliary/staged-api.rs file.
#![feature(const_trait_impl)]
#![feature(const_trait_impl, effects)]
#![feature(staged_api)]
#![stable(feature = "rust1", since = "1.0.0")]

View File

@ -1,20 +1,29 @@
error: const `impl` for trait `Try` which is not marked with `#[const_trait]`
--> $DIR/trait-default-body-stability.rs:18:12
error[E0015]: `?` cannot determine the branch of `T` in constant functions
--> $DIR/trait-default-body-stability.rs:44:9
|
LL | T?
| ^^
|
note: impl defined here, but it is not `const`
--> $DIR/trait-default-body-stability.rs:18:1
|
LL | impl const Try for 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
| ^^^^^^^^^^^^^^^^^^^^
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: const `impl` for trait `FromResidual` which is not marked with `#[const_trait]`
--> $DIR/trait-default-body-stability.rs:33:12
error[E0015]: `?` cannot convert from residual of `T` in constant functions
--> $DIR/trait-default-body-stability.rs:44:9
|
LL | T?
| ^^
|
note: impl defined here, but it is not `const`
--> $DIR/trait-default-body-stability.rs:33:1
|
LL | impl const FromResidual for 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
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0015`.

View File

@ -1,7 +1,7 @@
// known-bug: #110395
// FIXME run-pass
#![feature(const_trait_impl)]
#![feature(const_trait_impl, effects)]
#[const_trait]
trait Bar {

View File

@ -1,5 +1,5 @@
#![feature(staged_api)]
#![feature(const_trait_impl)]
#![feature(const_trait_impl, effects)]
#![stable(feature = "stable", since = "1.0.0")]
#[stable(feature = "stable", since = "1.0.0")]