Skip to content

Commit eb2b8be

Browse files
varkoryodaldevoid
andcommitted
Implement collect for const parameters
Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
1 parent 3001ae7 commit eb2b8be

File tree

1 file changed

+150
-85
lines changed

1 file changed

+150
-85
lines changed

src/librustc_typeck/collect.rs

Lines changed: 150 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,67 +1004,65 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty
10041004
ast_generics
10051005
.params
10061006
.iter()
1007-
.filter_map(|param| match param.kind {
1008-
GenericParamKind::Type {
1009-
ref default,
1010-
synthetic,
1011-
..
1012-
} => {
1013-
if param.name.ident().name == keywords::SelfUpper.name() {
1014-
span_bug!(
1015-
param.span,
1016-
"`Self` should not be the name of a regular parameter"
1017-
);
1018-
}
1019-
1020-
if !allow_defaults && default.is_some() {
1021-
if !tcx.features().default_type_parameter_fallback {
1022-
tcx.lint_hir(
1023-
lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
1024-
param.hir_id,
1007+
.filter_map(|param| {
1008+
let kind = match param.kind {
1009+
GenericParamKind::Type {
1010+
ref default,
1011+
synthetic,
1012+
..
1013+
} => {
1014+
if param.name.ident().name == keywords::SelfUpper.name() {
1015+
span_bug!(
10251016
param.span,
1026-
&format!(
1027-
"defaults for type parameters are only allowed in \
1028-
`struct`, `enum`, `type`, or `trait` definitions."
1029-
),
1017+
"`Self` should not be the name of a regular parameter"
10301018
);
10311019
}
1032-
}
10331020

1034-
let ty_param = ty::GenericParamDef {
1035-
index: type_start + i as u32,
1036-
name: param.name.ident().as_interned_str(),
1037-
def_id: tcx.hir().local_def_id_from_hir_id(param.hir_id),
1038-
pure_wrt_drop: param.pure_wrt_drop,
1039-
kind: ty::GenericParamDefKind::Type {
1021+
if !allow_defaults && default.is_some() {
1022+
if !tcx.features().default_type_parameter_fallback {
1023+
tcx.lint_node(
1024+
lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
1025+
param.hir_id,
1026+
param.span,
1027+
&format!(
1028+
"defaults for type parameters are only allowed in \
1029+
`struct`, `enum`, `type`, or `trait` definitions."
1030+
),
1031+
);
1032+
}
1033+
}
1034+
1035+
ty::GenericParamDefKind::Type {
10401036
has_default: default.is_some(),
10411037
object_lifetime_default: object_lifetime_defaults
10421038
.as_ref()
10431039
.map_or(rl::Set1::Empty, |o| o[i]),
10441040
synthetic,
1045-
},
1046-
};
1047-
i += 1;
1048-
Some(ty_param)
1049-
}
1050-
GenericParamKind::Const { .. } => {
1051-
if param.name.ident().name == keywords::SelfUpper.name() {
1052-
span_bug!(
1053-
param.span,
1054-
"`Self` should not be the name of a regular parameter",
1055-
);
1041+
}
10561042
}
1043+
GenericParamKind::Const { .. } => {
1044+
if param.name.ident().name == keywords::SelfUpper.name() {
1045+
span_bug!(
1046+
param.span,
1047+
"`Self` should not be the name of a regular parameter",
1048+
);
1049+
}
10571050

1058-
// Emit an error, but skip the parameter rather than aborting to
1059-
// continue to get other errors.
1060-
tcx.sess.struct_span_err(
1061-
param.span,
1062-
"const generics in any position are currently unsupported",
1063-
).emit();
1064-
None
1065-
}
1066-
_ => None,
1067-
}),
1051+
ty::GenericParamDefKind::Const
1052+
}
1053+
_ => return None,
1054+
};
1055+
1056+
let param_def = ty::GenericParamDef {
1057+
index: type_start + i as u32,
1058+
name: param.name.ident().as_interned_str(),
1059+
def_id: tcx.hir().local_def_id_from_hir_id(param.hir_id),
1060+
pure_wrt_drop: param.pure_wrt_drop,
1061+
kind,
1062+
};
1063+
i += 1;
1064+
Some(param_def)
1065+
})
10681066
);
10691067

10701068
// provide junk type parameter defs - the only place that
@@ -1284,44 +1282,111 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Ty<'tcx> {
12841282
tcx.mk_closure(def_id, substs)
12851283
}
12861284

1287-
Node::AnonConst(_) => match tcx.hir().get_by_hir_id(
1288-
tcx.hir().get_parent_node_by_hir_id(hir_id))
1289-
{
1290-
Node::Ty(&hir::Ty {
1291-
node: hir::TyKind::Array(_, ref constant),
1292-
..
1293-
})
1294-
| Node::Ty(&hir::Ty {
1295-
node: hir::TyKind::Typeof(ref constant),
1296-
..
1297-
})
1298-
| Node::Expr(&hir::Expr {
1299-
node: ExprKind::Repeat(_, ref constant),
1300-
..
1301-
}) if constant.hir_id == hir_id =>
1302-
{
1303-
tcx.types.usize
1304-
}
1285+
Node::AnonConst(_) => {
1286+
let parent_node = tcx.hir().get_by_hir_id(tcx.hir().get_parent_node_by_hir_id(hir_id));
1287+
match parent_node {
1288+
Node::Ty(&hir::Ty {
1289+
node: hir::TyKind::Array(_, ref constant),
1290+
..
1291+
})
1292+
| Node::Ty(&hir::Ty {
1293+
node: hir::TyKind::Typeof(ref constant),
1294+
..
1295+
})
1296+
| Node::Expr(&hir::Expr {
1297+
node: ExprKind::Repeat(_, ref constant),
1298+
..
1299+
}) if constant.hir_id == hir_id =>
1300+
{
1301+
tcx.types.usize
1302+
}
13051303

1306-
Node::Variant(&Spanned {
1307-
node:
1308-
VariantKind {
1309-
disr_expr: Some(ref e),
1310-
..
1311-
},
1312-
..
1313-
}) if e.hir_id == hir_id =>
1314-
{
1315-
tcx.adt_def(tcx.hir().get_parent_did_by_hir_id(hir_id))
1316-
.repr
1317-
.discr_type()
1318-
.to_ty(tcx)
1319-
}
1304+
Node::Variant(&Spanned {
1305+
node:
1306+
VariantKind {
1307+
disr_expr: Some(ref e),
1308+
..
1309+
},
1310+
..
1311+
}) if e.hir_id == hir_id =>
1312+
{
1313+
tcx.adt_def(tcx.hir().get_parent_did_by_hir_id(hir_id))
1314+
.repr
1315+
.discr_type()
1316+
.to_ty(tcx)
1317+
}
13201318

1321-
x => {
1322-
bug!("unexpected const parent in type_of_def_id(): {:?}", x);
1319+
Node::Ty(&hir::Ty { node: hir::TyKind::Path(_), .. }) |
1320+
Node::Expr(&hir::Expr { node: ExprKind::Struct(..), .. }) |
1321+
Node::Expr(&hir::Expr { node: ExprKind::Path(_), .. }) => {
1322+
let path = match parent_node {
1323+
Node::Ty(&hir::Ty { node: hir::TyKind::Path(ref path), .. }) |
1324+
Node::Expr(&hir::Expr { node: ExprKind::Path(ref path), .. }) => {
1325+
path
1326+
}
1327+
Node::Expr(&hir::Expr { node: ExprKind::Struct(ref path, ..), .. }) => {
1328+
&*path
1329+
}
1330+
_ => unreachable!(),
1331+
};
1332+
1333+
match path {
1334+
QPath::Resolved(_, ref path) => {
1335+
let mut arg_index = 0;
1336+
let mut found_const = false;
1337+
for seg in &path.segments {
1338+
if let Some(generic_args) = &seg.args {
1339+
let args = &generic_args.args;
1340+
for arg in args {
1341+
if let GenericArg::Const(ct) = arg {
1342+
if ct.value.id == node_id {
1343+
found_const = true;
1344+
break;
1345+
}
1346+
arg_index += 1;
1347+
}
1348+
}
1349+
}
1350+
}
1351+
// Sanity check to make sure everything is as expected.
1352+
if !found_const {
1353+
bug!("no arg matching AnonConst in path")
1354+
}
1355+
match path.def {
1356+
// We've encountered an `AnonConst` in some path, so we need to
1357+
// figure out which generic parameter it corresponds to and return
1358+
// the relevant type.
1359+
Def::Struct(def_id)
1360+
| Def::Union(def_id)
1361+
| Def::Enum(def_id)
1362+
| Def::Fn(def_id) => {
1363+
let generics = tcx.generics_of(def_id);
1364+
let mut param_index = 0;
1365+
for param in &generics.params {
1366+
if let ty::GenericParamDefKind::Const = param.kind {
1367+
if param_index == arg_index {
1368+
return tcx.type_of(param.def_id);
1369+
}
1370+
param_index += 1;
1371+
}
1372+
}
1373+
// This is no generic parameter associated with the arg. This is
1374+
// probably from an extra arg where one is not needed.
1375+
return tcx.types.err;
1376+
}
1377+
Def::Err => tcx.types.err,
1378+
x => bug!("unexpected const parent path def {:?}", x),
1379+
}
1380+
}
1381+
x => bug!("unexpected const parent path {:?}", x),
1382+
}
1383+
}
1384+
1385+
x => {
1386+
bug!("unexpected const parent in type_of_def_id(): {:?}", x);
1387+
}
13231388
}
1324-
},
1389+
}
13251390

13261391
Node::GenericParam(param) => match &param.kind {
13271392
hir::GenericParamKind::Type { default: Some(ref ty), .. } |

0 commit comments

Comments
 (0)