lower impl const to bind to host effect param
This commit is contained in:
parent
4f7bb9890c
commit
92f4c59e48
24 changed files with 236 additions and 137 deletions
|
@ -313,6 +313,16 @@ pub enum TraitBoundModifier {
|
||||||
MaybeConstMaybe,
|
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.
|
/// The AST represents all type param bounds as types.
|
||||||
/// `typeck::collect::compute_bounds` matches these against
|
/// `typeck::collect::compute_bounds` matches these against
|
||||||
/// the "special" built-in traits (see `middle::lang_items`) and
|
/// the "special" built-in traits (see `middle::lang_items`) and
|
||||||
|
|
|
@ -207,6 +207,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
&sym.path,
|
&sym.path,
|
||||||
ParamMode::Optional,
|
ParamMode::Optional,
|
||||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
hir::InlineAsmOperand::SymStatic { path, def_id }
|
hir::InlineAsmOperand::SymStatic { path, def_id }
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -100,6 +100,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
ParamMode::Optional,
|
ParamMode::Optional,
|
||||||
ParenthesizedGenericArgs::Err,
|
ParenthesizedGenericArgs::Err,
|
||||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||||
|
None,
|
||||||
));
|
));
|
||||||
let receiver = self.lower_expr(receiver);
|
let receiver = self.lower_expr(receiver);
|
||||||
let args =
|
let args =
|
||||||
|
@ -260,6 +261,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
path,
|
path,
|
||||||
ParamMode::Optional,
|
ParamMode::Optional,
|
||||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
hir::ExprKind::Path(qpath)
|
hir::ExprKind::Path(qpath)
|
||||||
}
|
}
|
||||||
|
@ -307,6 +309,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
&se.path,
|
&se.path,
|
||||||
ParamMode::Optional,
|
ParamMode::Optional,
|
||||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||||
|
None,
|
||||||
)),
|
)),
|
||||||
self.arena
|
self.arena
|
||||||
.alloc_from_iter(se.fields.iter().map(|x| self.lower_expr_field(x))),
|
.alloc_from_iter(se.fields.iter().map(|x| self.lower_expr_field(x))),
|
||||||
|
@ -1179,6 +1182,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
path,
|
path,
|
||||||
ParamMode::Optional,
|
ParamMode::Optional,
|
||||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
// Destructure like a tuple struct.
|
// Destructure like a tuple struct.
|
||||||
let tuple_struct_pat = hir::PatKind::TupleStruct(
|
let tuple_struct_pat = hir::PatKind::TupleStruct(
|
||||||
|
@ -1198,6 +1202,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
path,
|
path,
|
||||||
ParamMode::Optional,
|
ParamMode::Optional,
|
||||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
// Destructure like a unit struct.
|
// Destructure like a unit struct.
|
||||||
let unit_struct_pat = hir::PatKind::Path(qpath);
|
let unit_struct_pat = hir::PatKind::Path(qpath);
|
||||||
|
@ -1222,6 +1227,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
&se.path,
|
&se.path,
|
||||||
ParamMode::Optional,
|
ParamMode::Optional,
|
||||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
let fields_omitted = match &se.rest {
|
let fields_omitted = match &se.rest {
|
||||||
StructRest::Base(e) => {
|
StructRest::Base(e) => {
|
||||||
|
|
|
@ -85,6 +85,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
||||||
allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()),
|
allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()),
|
||||||
allow_gen_future: Some([sym::gen_future, sym::closure_track_caller][..].into()),
|
allow_gen_future: Some([sym::gen_future, sym::closure_track_caller][..].into()),
|
||||||
generics_def_id_map: Default::default(),
|
generics_def_id_map: Default::default(),
|
||||||
|
host_param_id: None,
|
||||||
};
|
};
|
||||||
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
|
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
|
||||||
|
|
||||||
|
@ -139,9 +140,25 @@ impl<'a, 'hir> ItemLowerer<'a, '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.
|
||||||
|
|
||||||
if let hir::ItemKind::Impl(impl_) = parent_hir.node().expect_item().kind {
|
match parent_hir.node().expect_item().kind {
|
||||||
|
hir::ItemKind::Impl(impl_) => {
|
||||||
lctx.is_in_trait_impl = impl_.of_trait.is_some();
|
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 {
|
match ctxt {
|
||||||
AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)),
|
AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)),
|
||||||
|
@ -384,6 +401,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
self.lower_generics(ast_generics, *constness, id, &itctx, |this| {
|
self.lower_generics(ast_generics, *constness, id, &itctx, |this| {
|
||||||
let trait_ref = trait_ref.as_ref().map(|trait_ref| {
|
let trait_ref = trait_ref.as_ref().map(|trait_ref| {
|
||||||
this.lower_trait_ref(
|
this.lower_trait_ref(
|
||||||
|
*constness,
|
||||||
trait_ref,
|
trait_ref,
|
||||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Trait),
|
&ImplTraitContext::Disallowed(ImplTraitPosition::Trait),
|
||||||
)
|
)
|
||||||
|
@ -414,7 +432,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
polarity,
|
polarity,
|
||||||
defaultness,
|
defaultness,
|
||||||
defaultness_span,
|
defaultness_span,
|
||||||
constness: self.lower_constness(*constness),
|
|
||||||
generics,
|
generics,
|
||||||
of_trait: trait_ref,
|
of_trait: trait_ref,
|
||||||
self_ty: lowered_ty,
|
self_ty: lowered_ty,
|
||||||
|
@ -1358,6 +1375,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();
|
let mut predicates: SmallVec<[hir::WherePredicate<'hir>; 4]> = SmallVec::new();
|
||||||
predicates.extend(generics.params.iter().filter_map(|param| {
|
predicates.extend(generics.params.iter().filter_map(|param| {
|
||||||
self.lower_generic_bound_predicate(
|
self.lower_generic_bound_predicate(
|
||||||
|
@ -1405,22 +1445,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
let impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds);
|
let impl_trait_bounds = std::mem::take(&mut self.impl_trait_bounds);
|
||||||
predicates.extend(impl_trait_bounds.into_iter());
|
predicates.extend(impl_trait_bounds.into_iter());
|
||||||
|
|
||||||
// Desugar `~const` bound in generics into an additional `const host: bool` param
|
if let Some((span, hir_id, def_id)) = host_param_parts {
|
||||||
// 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();
|
|
||||||
let const_node_id = self.next_node_id();
|
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 =
|
||||||
let anon_const: LocalDefId = self.create_def(def_id, const_node_id, DefPathData::AnonConst, span);
|
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_id = self.next_id();
|
||||||
let const_expr_id = self.next_id();
|
let const_expr_id = self.next_id();
|
||||||
let bool_id = self.next_id();
|
let bool_id = self.next_id();
|
||||||
|
@ -1430,14 +1459,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
|
|
||||||
let attr_id = self.tcx.sess.parse_sess.attr_id_generator.mk_attr_id();
|
let attr_id = self.tcx.sess.parse_sess.attr_id_generator.mk_attr_id();
|
||||||
|
|
||||||
let attrs = self.arena.alloc_from_iter([
|
let attrs = self.arena.alloc_from_iter([Attribute {
|
||||||
Attribute {
|
kind: AttrKind::Normal(P(NormalAttr::from_ident(Ident::new(
|
||||||
kind: AttrKind::Normal(P(NormalAttr::from_ident(Ident::new(sym::rustc_host, span)))),
|
sym::rustc_host,
|
||||||
|
span,
|
||||||
|
)))),
|
||||||
span,
|
span,
|
||||||
id: attr_id,
|
id: attr_id,
|
||||||
style: AttrStyle::Outer,
|
style: AttrStyle::Outer,
|
||||||
},
|
}]);
|
||||||
]);
|
|
||||||
self.attrs.insert(hir_id.local_id, attrs);
|
self.attrs.insert(hir_id.local_id, attrs);
|
||||||
|
|
||||||
let const_body = self.lower_body(|this| {
|
let const_body = self.lower_body(|this| {
|
||||||
|
@ -1476,7 +1506,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,
|
colon_span: None,
|
||||||
pure_wrt_drop: false,
|
pure_wrt_drop: false,
|
||||||
|
|
|
@ -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
|
/// 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.
|
/// field from the original parameter 'a to the new parameter 'a1.
|
||||||
generics_def_id_map: Vec<FxHashMap<LocalDefId, LocalDefId>>,
|
generics_def_id_map: Vec<FxHashMap<LocalDefId, LocalDefId>>,
|
||||||
|
|
||||||
|
host_param_id: Option<LocalDefId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
trait ResolverAstLoweringExt {
|
trait ResolverAstLoweringExt {
|
||||||
|
@ -1267,6 +1269,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
span: t.span
|
span: t.span
|
||||||
},
|
},
|
||||||
itctx,
|
itctx,
|
||||||
|
ast::Const::No,
|
||||||
);
|
);
|
||||||
let bounds = this.arena.alloc_from_iter([bound]);
|
let bounds = this.arena.alloc_from_iter([bound]);
|
||||||
let lifetime_bound = this.elided_dyn_bound(t.span);
|
let lifetime_bound = this.elided_dyn_bound(t.span);
|
||||||
|
@ -1277,7 +1280,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let id = self.lower_node_id(t.id);
|
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)
|
self.ty_path(id, t.span, qpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1361,10 +1364,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
this.arena.alloc_from_iter(bounds.iter().filter_map(|bound| match bound {
|
this.arena.alloc_from_iter(bounds.iter().filter_map(|bound| match bound {
|
||||||
GenericBound::Trait(
|
GenericBound::Trait(
|
||||||
ty,
|
ty,
|
||||||
TraitBoundModifier::None
|
modifier @ (TraitBoundModifier::None
|
||||||
| TraitBoundModifier::MaybeConst
|
| TraitBoundModifier::MaybeConst
|
||||||
| TraitBoundModifier::Negative,
|
| TraitBoundModifier::Negative),
|
||||||
) => Some(this.lower_poly_trait_ref(ty, itctx)),
|
) => {
|
||||||
|
Some(this.lower_poly_trait_ref(ty, itctx, modifier.to_constness()))
|
||||||
|
}
|
||||||
// `~const ?Bound` will cause an error during AST validation
|
// `~const ?Bound` will cause an error during AST validation
|
||||||
// anyways, so treat it like `?Bound` as compilation proceeds.
|
// anyways, so treat it like `?Bound` as compilation proceeds.
|
||||||
GenericBound::Trait(
|
GenericBound::Trait(
|
||||||
|
@ -2189,7 +2194,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
) -> hir::GenericBound<'hir> {
|
) -> hir::GenericBound<'hir> {
|
||||||
match tpb {
|
match tpb {
|
||||||
GenericBound::Trait(p, modifier) => hir::GenericBound::Trait(
|
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),
|
self.lower_trait_bound_modifier(*modifier),
|
||||||
),
|
),
|
||||||
GenericBound::Outlives(lifetime) => {
|
GenericBound::Outlives(lifetime) => {
|
||||||
|
@ -2332,8 +2337,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_trait_ref(&mut self, p: &TraitRef, itctx: &ImplTraitContext) -> hir::TraitRef<'hir> {
|
fn lower_trait_ref(
|
||||||
let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) {
|
&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,
|
hir::QPath::Resolved(None, path) => path,
|
||||||
qpath => panic!("lower_trait_ref: unexpected QPath `{qpath:?}`"),
|
qpath => panic!("lower_trait_ref: unexpected QPath `{qpath:?}`"),
|
||||||
};
|
};
|
||||||
|
@ -2345,10 +2362,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
&mut self,
|
&mut self,
|
||||||
p: &PolyTraitRef,
|
p: &PolyTraitRef,
|
||||||
itctx: &ImplTraitContext,
|
itctx: &ImplTraitContext,
|
||||||
|
constness: ast::Const,
|
||||||
) -> hir::PolyTraitRef<'hir> {
|
) -> hir::PolyTraitRef<'hir> {
|
||||||
let bound_generic_params =
|
let bound_generic_params =
|
||||||
self.lower_lifetime_binder(p.trait_ref.ref_id, &p.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) }
|
hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2702,6 +2720,57 @@ struct GenericArgsCtor<'hir> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'hir> 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 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 {
|
fn is_empty(&self) -> bool {
|
||||||
self.args.is_empty()
|
self.args.is_empty()
|
||||||
&& self.bindings.is_empty()
|
&& self.bindings.is_empty()
|
||||||
|
|
|
@ -38,6 +38,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
path,
|
path,
|
||||||
ParamMode::Optional,
|
ParamMode::Optional,
|
||||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct");
|
let (pats, ddpos) = self.lower_pat_tuple(pats, "tuple struct");
|
||||||
break hir::PatKind::TupleStruct(qpath, pats, ddpos);
|
break hir::PatKind::TupleStruct(qpath, pats, ddpos);
|
||||||
|
@ -54,6 +55,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
path,
|
path,
|
||||||
ParamMode::Optional,
|
ParamMode::Optional,
|
||||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
break hir::PatKind::Path(qpath);
|
break hir::PatKind::Path(qpath);
|
||||||
}
|
}
|
||||||
|
@ -64,6 +66,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
path,
|
path,
|
||||||
ParamMode::Optional,
|
ParamMode::Optional,
|
||||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
let fs = self.arena.alloc_from_iter(fields.iter().map(|f| {
|
let fs = self.arena.alloc_from_iter(fields.iter().map(|f| {
|
||||||
|
|
|
@ -23,6 +23,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
p: &Path,
|
p: &Path,
|
||||||
param_mode: ParamMode,
|
param_mode: ParamMode,
|
||||||
itctx: &ImplTraitContext,
|
itctx: &ImplTraitContext,
|
||||||
|
// constness of the impl/bound if this is a trait path
|
||||||
|
constness: Option<ast::Const>,
|
||||||
) -> hir::QPath<'hir> {
|
) -> hir::QPath<'hir> {
|
||||||
let qself_position = qself.as_ref().map(|q| q.position);
|
let qself_position = qself.as_ref().map(|q| q.position);
|
||||||
let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx));
|
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,
|
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 { constness } else { None },
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)),
|
)),
|
||||||
|
@ -119,6 +123,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
param_mode,
|
param_mode,
|
||||||
ParenthesizedGenericArgs::Err,
|
ParenthesizedGenericArgs::Err,
|
||||||
itctx,
|
itctx,
|
||||||
|
None,
|
||||||
));
|
));
|
||||||
let qpath = hir::QPath::TypeRelative(ty, hir_segment);
|
let qpath = hir::QPath::TypeRelative(ty, hir_segment);
|
||||||
|
|
||||||
|
@ -159,6 +164,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
param_mode,
|
param_mode,
|
||||||
ParenthesizedGenericArgs::Err,
|
ParenthesizedGenericArgs::Err,
|
||||||
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
})),
|
})),
|
||||||
span: self.lower_span(p.span),
|
span: self.lower_span(p.span),
|
||||||
|
@ -172,8 +178,9 @@ 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::Const>,
|
||||||
) -> hir::PathSegment<'hir> {
|
) -> 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() {
|
let (mut generic_args, infer_args) = if let Some(generic_args) = segment.args.as_deref() {
|
||||||
match generic_args {
|
match generic_args {
|
||||||
GenericArgs::AngleBracketed(data) => {
|
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 =
|
let has_lifetimes =
|
||||||
generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
|
generic_args.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)));
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
|
||||||
| hir::Node::AnonConst(_)
|
| hir::Node::AnonConst(_)
|
||||||
| hir::Node::ConstBlock(_)
|
| hir::Node::ConstBlock(_)
|
||||||
| hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => hir::Constness::Const,
|
| 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(..), .. }) => {
|
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.
|
||||||
|
|
|
@ -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 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 Some(parent) = tcx.hir().opt_parent_id(hir_id) else { return false };
|
||||||
let parent_def = tcx.hir().get(parent);
|
|
||||||
|
|
||||||
if !matches!(
|
if !tcx.is_const_trait_impl_raw(parent.owner.def_id.to_def_id()) {
|
||||||
parent_def,
|
|
||||||
hir::Node::Item(hir::Item {
|
|
||||||
kind: hir::ItemKind::Impl(hir::Impl { constness: hir::Constness::Const, .. }),
|
|
||||||
..
|
|
||||||
})
|
|
||||||
) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -145,10 +145,13 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
|
||||||
let implsrc = selcx.select(&obligation);
|
let implsrc = selcx.select(&obligation);
|
||||||
|
|
||||||
if let Ok(Some(ImplSource::UserDefined(data))) = implsrc {
|
if let Ok(Some(ImplSource::UserDefined(data))) = implsrc {
|
||||||
|
// FIXME(effects) revisit this
|
||||||
|
if !tcx.is_const_trait_impl_raw(data.impl_def_id) {
|
||||||
let span = tcx.def_span(data.impl_def_id);
|
let span = tcx.def_span(data.impl_def_id);
|
||||||
err.subdiagnostic(errors::NonConstImplNote { span });
|
err.subdiagnostic(errors::NonConstImplNote { span });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -3357,7 +3357,6 @@ pub struct Impl<'hir> {
|
||||||
// We do not put a `Span` in `Defaultness` because it breaks foreign crate metadata
|
// 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.
|
// decoding as `Span`s cannot be decoded when a `Session` is not available.
|
||||||
pub defaultness_span: Option<Span>,
|
pub defaultness_span: Option<Span>,
|
||||||
pub constness: Constness,
|
|
||||||
pub generics: &'hir Generics<'hir>,
|
pub generics: &'hir Generics<'hir>,
|
||||||
|
|
||||||
/// The trait being implemented, if any.
|
/// The trait being implemented, if any.
|
||||||
|
|
|
@ -522,7 +522,6 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
|
||||||
unsafety: _,
|
unsafety: _,
|
||||||
defaultness: _,
|
defaultness: _,
|
||||||
polarity: _,
|
polarity: _,
|
||||||
constness: _,
|
|
||||||
defaultness_span: _,
|
defaultness_span: _,
|
||||||
ref generics,
|
ref generics,
|
||||||
ref of_trait,
|
ref of_trait,
|
||||||
|
|
|
@ -532,6 +532,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
if let Err(guar) = ty.error_reported() {
|
if let Err(guar) = ty.error_reported() {
|
||||||
return ty::Const::new_error(tcx, guar, ty).into();
|
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 {
|
if !infer_args && has_default {
|
||||||
tcx.const_param_default(param.def_id)
|
tcx.const_param_default(param.def_id)
|
||||||
.instantiate(tcx, args.unwrap())
|
.instantiate(tcx, args.unwrap())
|
||||||
|
@ -659,7 +660,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
&self,
|
&self,
|
||||||
trait_ref: &hir::TraitRef<'_>,
|
trait_ref: &hir::TraitRef<'_>,
|
||||||
self_ty: Ty<'tcx>,
|
self_ty: Ty<'tcx>,
|
||||||
constness: ty::BoundConstness,
|
|
||||||
) -> ty::TraitRef<'tcx> {
|
) -> ty::TraitRef<'tcx> {
|
||||||
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter(), |_| {});
|
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,
|
self_ty,
|
||||||
trait_ref.path.segments.last().unwrap(),
|
trait_ref.path.segments.last().unwrap(),
|
||||||
true,
|
true,
|
||||||
constness,
|
ty::BoundConstness::NotConst,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -849,6 +849,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
self_ty: Ty<'tcx>,
|
self_ty: Ty<'tcx>,
|
||||||
trait_segment: &hir::PathSegment<'_>,
|
trait_segment: &hir::PathSegment<'_>,
|
||||||
is_impl: bool,
|
is_impl: bool,
|
||||||
|
// FIXME(effects) move all host param things in astconv to hir lowering
|
||||||
constness: ty::BoundConstness,
|
constness: ty::BoundConstness,
|
||||||
) -> ty::TraitRef<'tcx> {
|
) -> ty::TraitRef<'tcx> {
|
||||||
let (generic_args, _) = self.create_args_for_ast_trait_ref(
|
let (generic_args, _) = self.create_args_for_ast_trait_ref(
|
||||||
|
@ -2712,11 +2713,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
};
|
};
|
||||||
let i = hir.get_parent(fn_hir_id).expect_item().expect_impl();
|
let i = hir.get_parent(fn_hir_id).expect_item().expect_impl();
|
||||||
|
|
||||||
let trait_ref = self.instantiate_mono_trait_ref(
|
let trait_ref =
|
||||||
i.of_trait.as_ref()?,
|
self.instantiate_mono_trait_ref(i.of_trait.as_ref()?, self.ast_ty_to_ty(i.self_ty));
|
||||||
self.ast_ty_to_ty(i.self_ty),
|
|
||||||
ty::BoundConstness::NotConst,
|
|
||||||
);
|
|
||||||
|
|
||||||
let assoc = tcx.associated_items(trait_ref.def_id).find_by_name_and_kind(
|
let assoc = tcx.associated_items(trait_ref.def_id).find_by_name_and_kind(
|
||||||
tcx,
|
tcx,
|
||||||
|
|
|
@ -1358,23 +1358,19 @@ fn impl_trait_ref(
|
||||||
.of_trait
|
.of_trait
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|ast_trait_ref| {
|
.map(|ast_trait_ref| {
|
||||||
let selfty = tcx.type_of(def_id).instantiate_identity();
|
check_impl_constness(
|
||||||
icx.astconv().instantiate_mono_trait_ref(
|
tcx,
|
||||||
|
tcx.is_const_trait_impl_raw(def_id.to_def_id()),
|
||||||
ast_trait_ref,
|
ast_trait_ref,
|
||||||
selfty,
|
);
|
||||||
check_impl_constness(tcx, impl_.constness, ast_trait_ref),
|
let selfty = tcx.type_of(def_id).instantiate_identity();
|
||||||
)
|
icx.astconv().instantiate_mono_trait_ref(ast_trait_ref, selfty)
|
||||||
})
|
})
|
||||||
.map(ty::EarlyBinder::bind)
|
.map(ty::EarlyBinder::bind)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_impl_constness(
|
fn check_impl_constness(tcx: TyCtxt<'_>, is_const: bool, ast_trait_ref: &hir::TraitRef<'_>) {
|
||||||
tcx: TyCtxt<'_>,
|
if is_const {
|
||||||
constness: hir::Constness,
|
|
||||||
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) {
|
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();
|
let trait_name = tcx.item_name(trait_def_id).to_string();
|
||||||
tcx.sess.emit_err(errors::ConstImplForNonConstTrait {
|
tcx.sess.emit_err(errors::ConstImplForNonConstTrait {
|
||||||
|
@ -1384,12 +1380,7 @@ fn check_impl_constness(
|
||||||
marking: (),
|
marking: (),
|
||||||
adding: (),
|
adding: (),
|
||||||
});
|
});
|
||||||
ty::BoundConstness::NotConst
|
|
||||||
} else {
|
|
||||||
ty::BoundConstness::ConstIfConst
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
hir::Constness::NotConst => ty::BoundConstness::NotConst,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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:?}");
|
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 {
|
Some(ty::GenericParamDef {
|
||||||
|
|
|
@ -578,6 +578,9 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
|
||||||
MissingTypesOrConsts { .. } => {
|
MissingTypesOrConsts { .. } => {
|
||||||
self.suggest_adding_type_and_const_args(err);
|
self.suggest_adding_type_and_const_args(err);
|
||||||
}
|
}
|
||||||
|
ExcessTypesOrConsts { .. } => {
|
||||||
|
// this can happen with `~const T` where T isn't a const_trait.
|
||||||
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -626,7 +626,6 @@ impl<'a> State<'a> {
|
||||||
unsafety,
|
unsafety,
|
||||||
polarity,
|
polarity,
|
||||||
defaultness,
|
defaultness,
|
||||||
constness,
|
|
||||||
defaultness_span: _,
|
defaultness_span: _,
|
||||||
generics,
|
generics,
|
||||||
ref of_trait,
|
ref of_trait,
|
||||||
|
@ -643,10 +642,6 @@ impl<'a> State<'a> {
|
||||||
self.space();
|
self.space();
|
||||||
}
|
}
|
||||||
|
|
||||||
if constness == hir::Constness::Const {
|
|
||||||
self.word_nbsp("const");
|
|
||||||
}
|
|
||||||
|
|
||||||
if let hir::ImplPolarity::Negative(_) = polarity {
|
if let hir::ImplPolarity::Negative(_) = polarity {
|
||||||
self.word("!");
|
self.word("!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -767,9 +767,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
) {
|
) {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
|
|
||||||
if !tcx.features().effects || tcx.sess.opts.unstable_opts.unleash_the_miri_inside_of_you {
|
// fast-reject if callee doesn't have the host effect param (non-const)
|
||||||
return;
|
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.
|
// Compute the constness required by the context.
|
||||||
let context = tcx.hir().enclosing_body_owner(call_expr_hir);
|
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) {
|
if tcx.has_attr(context.to_def_id(), sym::rustc_do_not_const_check) {
|
||||||
trace!("do not const check this context");
|
trace!("do not const check this context");
|
||||||
return;
|
host_always_on = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let effect = match const_context {
|
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::Static(_) | hir::ConstContext::Const) => tcx.consts.false_,
|
||||||
Some(hir::ConstContext::ConstFn) => {
|
Some(hir::ConstContext::ConstFn) => {
|
||||||
let args = ty::GenericArgs::identity_for_item(tcx, context);
|
let args = ty::GenericArgs::identity_for_item(tcx, context);
|
||||||
|
@ -792,12 +799,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
None => tcx.consts.true_,
|
None => tcx.consts.true_,
|
||||||
};
|
};
|
||||||
|
|
||||||
let generics = tcx.generics_of(callee_did);
|
|
||||||
|
|
||||||
trace!(?effect, ?generics, ?callee_args);
|
trace!(?effect, ?generics, ?callee_args);
|
||||||
|
|
||||||
if let Some(idx) = generics.host_effect_index {
|
let param = callee_args.const_at(host_effect_index);
|
||||||
let param = callee_args.const_at(idx);
|
|
||||||
let cause = self.misc(span);
|
let cause = self.misc(span);
|
||||||
match self.at(&cause, self.param_env).eq(infer::DefineOpaqueTypes::No, effect, param) {
|
match self.at(&cause, self.param_env).eq(infer::DefineOpaqueTypes::No, effect, param) {
|
||||||
Ok(infer::InferOk { obligations, value: () }) => {
|
Ok(infer::InferOk { obligations, value: () }) => {
|
||||||
|
@ -809,7 +813,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn confirm_overloaded_call(
|
fn confirm_overloaded_call(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -1349,7 +1349,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GenericParamDefKind::Const { has_default } => {
|
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)
|
tcx.const_param_default(param.def_id)
|
||||||
.instantiate(tcx, args.unwrap())
|
.instantiate(tcx, args.unwrap())
|
||||||
.into()
|
.into()
|
||||||
|
|
|
@ -1963,9 +1963,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 { 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))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2841,6 +2841,11 @@ define_print_and_forward_display! {
|
||||||
|
|
||||||
ty::TraitPredicate<'tcx> {
|
ty::TraitPredicate<'tcx> {
|
||||||
p!(print(self.trait_ref.self_ty()), ": ");
|
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
|
// FIXME(effects) print `~const` here
|
||||||
if let ty::ImplPolarity::Negative = self.polarity {
|
if let ty::ImplPolarity::Negative = self.polarity {
|
||||||
p!("!");
|
p!("!");
|
||||||
|
|
|
@ -732,13 +732,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
|
||||||
// For implementations of traits, check the stability of each item
|
// For implementations of traits, check the stability of each item
|
||||||
// individually as it's possible to have a stable trait with unstable
|
// individually as it's possible to have a stable trait with unstable
|
||||||
// items.
|
// items.
|
||||||
hir::ItemKind::Impl(hir::Impl {
|
hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref t), self_ty, items, .. }) => {
|
||||||
of_trait: Some(ref t),
|
|
||||||
self_ty,
|
|
||||||
items,
|
|
||||||
constness,
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
let features = self.tcx.features();
|
let features = self.tcx.features();
|
||||||
if features.staged_api {
|
if features.staged_api {
|
||||||
let attrs = self.tcx.hir().attrs(item.hir_id());
|
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
|
// `#![feature(const_trait_impl)]` is unstable, so any impl declared stable
|
||||||
// needs to have an error emitted.
|
// needs to have an error emitted.
|
||||||
if features.const_trait_impl
|
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())
|
&& const_stab.is_some_and(|(stab, _)| stab.is_const_stable())
|
||||||
{
|
{
|
||||||
self.tcx.sess.emit_err(errors::TraitImplConstStable { span: item.span });
|
self.tcx.sess.emit_err(errors::TraitImplConstStable { span: item.span });
|
||||||
|
|
|
@ -3102,27 +3102,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||||
) -> UnsatisfiedConst {
|
) -> UnsatisfiedConst {
|
||||||
let unsatisfied_const = UnsatisfiedConst(false);
|
let unsatisfied_const = UnsatisfiedConst(false);
|
||||||
// FIXME(effects)
|
// 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
|
unsatisfied_const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// known-bug: #110395
|
// known-bug: #110395
|
||||||
#![feature(const_trait_impl)]
|
#![feature(const_trait_impl, effects)]
|
||||||
#![feature(const_mut_refs)]
|
#![feature(const_mut_refs)]
|
||||||
#![cfg_attr(precise, feature(const_precise_live_drops))]
|
#![cfg_attr(precise, feature(const_precise_live_drops))]
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue