Skip to content

Commit 046675f

Browse files
committed
init impl
1 parent 8d670b9 commit 046675f

File tree

24 files changed

+546
-28
lines changed

24 files changed

+546
-28
lines changed

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2396,6 +2396,35 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
23962396
};
23972397

23982398
match &expr.kind {
2399+
ExprKind::Call(func, args) if let ExprKind::Path(qself, path) = &func.kind => {
2400+
let qpath = self.lower_qpath(
2401+
func.id,
2402+
qself,
2403+
path,
2404+
ParamMode::Explicit,
2405+
AllowReturnTypeNotation::No,
2406+
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
2407+
None,
2408+
);
2409+
2410+
let lowered_args = self.arena.alloc_from_iter(args.iter().map(|arg| {
2411+
let const_arg = if let ExprKind::ConstBlock(anon_const) = &arg.kind {
2412+
let def_id = self.local_def_id(anon_const.id);
2413+
let def_kind = self.tcx.def_kind(def_id);
2414+
assert_eq!(DefKind::AnonConst, def_kind);
2415+
self.lower_anon_const_to_const_arg_direct(anon_const)
2416+
} else {
2417+
self.lower_expr_to_const_arg_direct(arg)
2418+
};
2419+
2420+
&*self.arena.alloc(const_arg)
2421+
}));
2422+
2423+
ConstArg {
2424+
hir_id: self.next_id(),
2425+
kind: hir::ConstArgKind::TupleCall(qpath, lowered_args),
2426+
}
2427+
}
23992428
ExprKind::Path(qself, path) => {
24002429
let qpath = self.lower_qpath(
24012430
expr.id,
@@ -2460,7 +2489,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
24602489
&& let StmtKind::Expr(expr) = &stmt.kind
24612490
&& matches!(
24622491
expr.kind,
2463-
ExprKind::Block(..) | ExprKind::Path(..) | ExprKind::Struct(..)
2492+
ExprKind::Block(..)
2493+
| ExprKind::Path(..)
2494+
| ExprKind::Struct(..)
2495+
| ExprKind::Call(..)
24642496
)
24652497
{
24662498
return self.lower_expr_to_const_arg_direct(expr);

compiler/rustc_hir/src/hir.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@ impl<'hir, Unambig> ConstArg<'hir, Unambig> {
499499
match self.kind {
500500
ConstArgKind::Struct(path, _) => path.span(),
501501
ConstArgKind::Path(path) => path.span(),
502+
ConstArgKind::TupleCall(path, _) => path.span(),
502503
ConstArgKind::Anon(anon) => anon.span,
503504
ConstArgKind::Error(span, _) => span,
504505
ConstArgKind::Infer(span, _) => span,
@@ -519,6 +520,8 @@ pub enum ConstArgKind<'hir, Unambig = ()> {
519520
Anon(&'hir AnonConst),
520521
/// Represents construction of struct/struct variants
521522
Struct(QPath<'hir>, &'hir [&'hir ConstArgExprField<'hir>]),
523+
/// Tuple constructor variant
524+
TupleCall(QPath<'hir>, &'hir [&'hir ConstArg<'hir>]),
522525
/// Error const
523526
Error(Span, ErrorGuaranteed),
524527
/// This variant is not always used to represent inference consts, sometimes

compiler/rustc_hir/src/intravisit.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,6 +1090,13 @@ pub fn walk_const_arg<'v, V: Visitor<'v>>(
10901090

10911091
V::Result::output()
10921092
}
1093+
ConstArgKind::TupleCall(qpath, args) => {
1094+
try_visit!(visitor.visit_qpath(qpath, *hir_id, qpath.span()));
1095+
for arg in *args {
1096+
try_visit!(visitor.visit_const_arg_unambig(*arg));
1097+
}
1098+
V::Result::output()
1099+
}
10931100
ConstArgKind::Path(qpath) => visitor.visit_qpath(qpath, *hir_id, qpath.span()),
10941101
ConstArgKind::Anon(anon) => visitor.visit_anon_const(*anon),
10951102
ConstArgKind::Error(_, _) => V::Result::output(), // errors and spans are not important

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 133 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ pub enum PermitVariants {
314314
enum TypeRelativePath<'tcx> {
315315
AssocItem(DefId, GenericArgsRef<'tcx>),
316316
Variant { adt: Ty<'tcx>, variant_did: DefId },
317+
Ctor { ctor_def_id: DefId, args: GenericArgsRef<'tcx> },
317318
}
318319

319320
/// New-typed boolean indicating whether explicit late-bound lifetimes
@@ -1261,6 +1262,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
12611262
TypeRelativePath::Variant { adt, variant_did } => {
12621263
Ok((adt, DefKind::Variant, variant_did))
12631264
}
1265+
TypeRelativePath::Ctor { .. } => {
1266+
let e = tcx.dcx().span_err(span, "expected type, found tuple constructor");
1267+
Err(e)
1268+
}
12641269
}
12651270
}
12661271

@@ -1294,6 +1299,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
12941299
}
12951300
(def_id, args)
12961301
}
1302+
TypeRelativePath::Ctor { ctor_def_id, args } => {
1303+
return Ok(ty::Const::zero_sized(tcx, Ty::new_fn_def(tcx, ctor_def_id, args)));
1304+
}
12971305
// FIXME(mgca): implement support for this once ready to support all adt ctor expressions,
12981306
// not just const ctors
12991307
TypeRelativePath::Variant { .. } => {
@@ -1326,6 +1334,23 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
13261334
.iter()
13271335
.find(|vd| tcx.hygienic_eq(segment.ident, vd.ident(tcx), adt_def.did()));
13281336
if let Some(variant_def) = variant_def {
1337+
// FIXME(mgca): do we want constructor resolutions to take priority over
1338+
// other possible resolutions?
1339+
if matches!(mode, LowerTypeRelativePathMode::Const)
1340+
&& let Some((CtorKind::Fn, ctor_def_id)) = variant_def.ctor
1341+
{
1342+
tcx.check_stability(variant_def.def_id, Some(qpath_hir_id), span, None);
1343+
let _ = self.prohibit_generic_args(
1344+
slice::from_ref(segment).iter(),
1345+
GenericsArgsErrExtend::EnumVariant {
1346+
qself: hir_self_ty,
1347+
assoc_segment: segment,
1348+
adt_def,
1349+
},
1350+
);
1351+
let ty::Adt(_, enum_args) = self_ty.kind() else { unreachable!() };
1352+
return Ok(TypeRelativePath::Ctor { ctor_def_id, args: enum_args });
1353+
}
13291354
if let PermitVariants::Yes = mode.permit_variants() {
13301355
tcx.check_stability(variant_def.def_id, Some(qpath_hir_id), span, None);
13311356
let _ = self.prohibit_generic_args(
@@ -2266,12 +2291,106 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
22662291
hir::ConstArgKind::Struct(qpath, inits) => {
22672292
self.lower_const_arg_struct(hir_id, qpath, inits, const_arg.span())
22682293
}
2294+
hir::ConstArgKind::TupleCall(qpath, args) => {
2295+
self.lower_const_arg_tuple_call(hir_id, qpath, args, const_arg.span())
2296+
}
22692297
hir::ConstArgKind::Anon(anon) => self.lower_const_arg_anon(anon),
22702298
hir::ConstArgKind::Infer(span, ()) => self.ct_infer(None, span),
22712299
hir::ConstArgKind::Error(_, e) => ty::Const::new_error(tcx, e),
22722300
}
22732301
}
22742302

2303+
fn lower_const_arg_tuple_call(
2304+
&self,
2305+
hir_id: HirId,
2306+
qpath: hir::QPath<'tcx>,
2307+
args: &'tcx [&'tcx hir::ConstArg<'tcx>],
2308+
span: Span,
2309+
) -> Const<'tcx> {
2310+
let tcx = self.tcx();
2311+
2312+
let non_adt_or_variant_res = || {
2313+
let e = tcx.dcx().span_err(span, "tuple constructor with invalid base path");
2314+
ty::Const::new_error(tcx, e)
2315+
};
2316+
2317+
let ctor_const = match qpath {
2318+
hir::QPath::Resolved(maybe_qself, path) => {
2319+
let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself));
2320+
self.lower_resolved_const_path(opt_self_ty, path, hir_id)
2321+
}
2322+
hir::QPath::TypeRelative(hir_self_ty, segment) => {
2323+
let self_ty = self.lower_ty(hir_self_ty);
2324+
match self.lower_type_relative_const_path(
2325+
self_ty,
2326+
hir_self_ty,
2327+
segment,
2328+
hir_id,
2329+
span,
2330+
) {
2331+
Ok(c) => c,
2332+
Err(_) => return non_adt_or_variant_res(),
2333+
}
2334+
}
2335+
};
2336+
2337+
let Some(value) = ctor_const.try_to_value() else {
2338+
return non_adt_or_variant_res();
2339+
};
2340+
2341+
let (adt_def, adt_args, variant_did) = match value.ty.kind() {
2342+
ty::FnDef(def_id, fn_args)
2343+
if let DefKind::Ctor(CtorOf::Variant, _) = tcx.def_kind(*def_id) =>
2344+
{
2345+
let parent_did = tcx.parent(*def_id);
2346+
let enum_did = tcx.parent(parent_did);
2347+
(tcx.adt_def(enum_did), fn_args, parent_did)
2348+
}
2349+
ty::FnDef(def_id, fn_args)
2350+
if let DefKind::Ctor(CtorOf::Struct, _) = tcx.def_kind(*def_id) =>
2351+
{
2352+
let parent_did = tcx.parent(*def_id);
2353+
(tcx.adt_def(parent_did), fn_args, parent_did)
2354+
}
2355+
_ => return non_adt_or_variant_res(),
2356+
};
2357+
2358+
let variant_def = adt_def.variant_with_id(variant_did);
2359+
let variant_idx = adt_def.variant_index_with_id(variant_did).as_u32();
2360+
2361+
if args.len() != variant_def.fields.len() {
2362+
let e = tcx.dcx().span_err(
2363+
span,
2364+
format!(
2365+
"tuple constructor has {} arguments but {} were provided",
2366+
variant_def.fields.len(),
2367+
args.len()
2368+
),
2369+
);
2370+
return ty::Const::new_error(tcx, e);
2371+
}
2372+
2373+
let fields = variant_def
2374+
.fields
2375+
.iter()
2376+
.zip(args)
2377+
.map(|(field_def, arg)| {
2378+
self.lower_const_arg(arg, FeedConstTy::Param(field_def.did, adt_args))
2379+
})
2380+
.collect::<Vec<_>>();
2381+
2382+
let opt_discr_const = if adt_def.is_enum() {
2383+
let valtree = ty::ValTree::from_scalar_int(tcx, variant_idx.into());
2384+
Some(ty::Const::new_value(tcx, valtree, tcx.types.u32))
2385+
} else {
2386+
None
2387+
};
2388+
2389+
let valtree = ty::ValTree::from_branches(tcx, opt_discr_const.into_iter().chain(fields));
2390+
let adt_ty = Ty::new_adt(tcx, adt_def, adt_args);
2391+
ty::Const::new_value(tcx, valtree, adt_ty)
2392+
}
2393+
22752394
fn lower_const_arg_struct(
22762395
&self,
22772396
hir_id: HirId,
@@ -2403,6 +2522,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
24032522
let args = self.lower_generic_args_of_path_segment(span, did, segment);
24042523
ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args))
24052524
}
2525+
Res::Def(DefKind::Ctor(_, CtorKind::Fn), did) => {
2526+
assert_eq!(opt_self_ty, None);
2527+
let [leading_segments @ .., segment] = path.segments else { bug!() };
2528+
let _ = self
2529+
.prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None);
2530+
let parent_did = tcx.parent(did);
2531+
let generics_did = if let DefKind::Ctor(CtorOf::Variant, _) = tcx.def_kind(did) {
2532+
tcx.parent(parent_did)
2533+
} else {
2534+
parent_did
2535+
};
2536+
let args = self.lower_generic_args_of_path_segment(span, generics_did, segment);
2537+
ty::Const::zero_sized(tcx, Ty::new_fn_def(tcx, did, args))
2538+
}
24062539
Res::Def(DefKind::AssocConst, did) => {
24072540
let trait_segment = if let [modules @ .., trait_, _item] = path.segments {
24082541
let _ = self.prohibit_generic_args(modules.iter(), GenericsArgsErrExtend::None);
@@ -2438,9 +2571,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
24382571
DefKind::Mod
24392572
| DefKind::Enum
24402573
| DefKind::Variant
2441-
| DefKind::Ctor(CtorOf::Variant, CtorKind::Fn)
24422574
| DefKind::Struct
2443-
| DefKind::Ctor(CtorOf::Struct, CtorKind::Fn)
24442575
| DefKind::OpaqueTy
24452576
| DefKind::TyAlias
24462577
| DefKind::TraitAlias

compiler/rustc_hir_pretty/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1139,6 +1139,7 @@ impl<'a> State<'a> {
11391139
match &const_arg.kind {
11401140
// FIXME(mgca): proper printing for struct exprs
11411141
ConstArgKind::Struct(..) => self.word("/* STRUCT EXPR */"),
1142+
ConstArgKind::TupleCall(..) => self.word("/* TUPLE CALL */"),
11421143
ConstArgKind::Path(qpath) => self.print_qpath(qpath, true),
11431144
ConstArgKind::Anon(anon) => self.print_anon_const(anon),
11441145
ConstArgKind::Error(_, _) => self.word("/*ERROR*/"),

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1441,6 +1441,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
14411441
// Skip encoding defs for these as they should not have had a `DefId` created
14421442
hir::ConstArgKind::Error(..)
14431443
| hir::ConstArgKind::Struct(..)
1444+
| hir::ConstArgKind::TupleCall(..)
14441445
| hir::ConstArgKind::Path(..)
14451446
| hir::ConstArgKind::Infer(..) => true,
14461447
hir::ConstArgKind::Anon(..) => false,

compiler/rustc_resolve/src/def_collector.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
419419

420420
// Avoid overwriting `const_arg_context` as we may want to treat const blocks
421421
// as being anon consts if we are inside a const argument.
422-
ExprKind::Struct(_) => return visit::walk_expr(self, expr),
422+
ExprKind::Struct(_) | ExprKind::Call(..) => return visit::walk_expr(self, expr),
423423
// FIXME(mgca): we may want to handle block labels in some manner
424424
ExprKind::Block(block, _) if let [stmt] = block.stmts.as_slice() => match stmt.kind {
425425
// FIXME(mgca): this probably means that mac calls that expand

src/librustdoc/clean/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,9 @@ pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg<'tcx>) -> ConstantKind
323323
// FIXME(mgca): proper printing :3
324324
ConstantKind::Path { path: "/* STRUCT EXPR */".to_string().into() }
325325
}
326+
hir::ConstArgKind::TupleCall(..) => {
327+
ConstantKind::Path { path: "/* TUPLE CALL */".to_string().into() }
328+
}
326329
hir::ConstArgKind::Anon(anon) => ConstantKind::Anonymous { body: anon.body },
327330
hir::ConstArgKind::Infer(..) | hir::ConstArgKind::Error(..) => ConstantKind::Infer,
328331
}
@@ -1804,7 +1807,9 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
18041807
let ct = cx.tcx.normalize_erasing_regions(typing_env, ct);
18051808
print_const(cx, ct)
18061809
}
1807-
hir::ConstArgKind::Struct(..) | hir::ConstArgKind::Path(..) => {
1810+
hir::ConstArgKind::Struct(..)
1811+
| hir::ConstArgKind::Path(..)
1812+
| hir::ConstArgKind::TupleCall(..) => {
18081813
let ct = lower_const_arg_for_rustdoc(cx.tcx, const_arg, FeedConstTy::No);
18091814
print_const(cx, ct)
18101815
}

src/tools/clippy/clippy_lints/src/utils/author.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
320320
self.body(field!(anon_const.body));
321321
},
322322
ConstArgKind::Struct(..) => chain!(self, "let ConstArgKind::Struct(..) = {const_arg}.kind"),
323+
ConstArgKind::TupleCall(..) => chain!(self, "let ConstArgKind::TupleCall(..) = {const_arg}.kind"),
323324
ConstArgKind::Infer(..) => chain!(self, "let ConstArgKind::Infer(..) = {const_arg}.kind"),
324325
ConstArgKind::Error(..) => chain!(self, "let ConstArgKind::Error(..) = {const_arg}.kind"),
325326
}

src/tools/clippy/clippy_utils/src/consts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1140,7 +1140,7 @@ pub fn const_item_rhs_to_expr<'tcx>(tcx: TyCtxt<'tcx>, ct_rhs: ConstItemRhs<'tcx
11401140
ConstItemRhs::Body(body_id) => Some(tcx.hir_body(body_id).value),
11411141
ConstItemRhs::TypeConst(const_arg) => match const_arg.kind {
11421142
ConstArgKind::Anon(anon) => Some(tcx.hir_body(anon.body).value),
1143-
ConstArgKind::Struct(..) | ConstArgKind::Path(_) | ConstArgKind::Error(..) | ConstArgKind::Infer(..) => {
1143+
ConstArgKind::Struct(..) | ConstArgKind::TupleCall(..) | ConstArgKind::Path(_) | ConstArgKind::Error(..) | ConstArgKind::Infer(..) => {
11441144
None
11451145
},
11461146
},

0 commit comments

Comments
 (0)