Skip to content

Commit fb6cfde

Browse files
author
Gabriel Smith
committed
rustc: lowering: Lower type args as const args when resolved in value
namespace
1 parent 7b4642f commit fb6cfde

File tree

1 file changed

+56
-5
lines changed

1 file changed

+56
-5
lines changed

src/librustc/hir/lowering.rs

+56-5
Original file line numberDiff line numberDiff line change
@@ -1155,13 +1155,64 @@ impl<'a> LoweringContext<'a> {
11551155
}
11561156
}
11571157

1158-
fn lower_generic_arg(&mut self,
1159-
arg: &ast::GenericArg,
1160-
itctx: ImplTraitContext<'_>)
1161-
-> hir::GenericArg {
1158+
fn lower_generic_arg(
1159+
&mut self,
1160+
arg: &ast::GenericArg,
1161+
itctx: ImplTraitContext<'_>
1162+
) -> hir::GenericArg {
11621163
match arg {
11631164
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(&lt)),
1164-
ast::GenericArg::Type(ty) => GenericArg::Type(self.lower_ty_direct(&ty, itctx)),
1165+
ast::GenericArg::Type(ty) => {
1166+
// We parse const arguments as path types as we cannot distiguish them durring
1167+
// parsing. We try to resolve that ambiguity by attempting resolution in both the
1168+
// type and value namespaces. If we resolved the path in the value namespace, we
1169+
// transform it into a generic const argument.
1170+
if let TyKind::Path(ref qself, ref path) = ty.kind {
1171+
if let Some(partial_res) = self.resolver.get_partial_res(ty.id) {
1172+
let res = partial_res.base_res();
1173+
if !res.matches_ns(Namespace::TypeNS) {
1174+
debug!(
1175+
"lower_generic_arg: Lowering type argument as const argument: {:?}",
1176+
ty,
1177+
);
1178+
1179+
// Construct a AnonConst where the expr is the "ty"'s path.
1180+
1181+
let parent_def_index =
1182+
self.current_hir_id_owner.last().unwrap().0;
1183+
let node_id = self.resolver.next_node_id();
1184+
1185+
// Add a definition for the in-band const def.
1186+
self.resolver.definitions().create_def_with_parent(
1187+
parent_def_index,
1188+
node_id,
1189+
DefPathData::AnonConst,
1190+
ExpnId::root(),
1191+
ty.span,
1192+
);
1193+
1194+
let path_expr = Expr {
1195+
id: ty.id,
1196+
kind: ExprKind::Path(qself.clone(), path.clone()),
1197+
span: ty.span,
1198+
attrs: ThinVec::new(),
1199+
};
1200+
1201+
let ct = self.with_new_scopes(|this| {
1202+
hir::AnonConst {
1203+
hir_id: this.lower_node_id(node_id),
1204+
body: this.lower_const_body(&path_expr),
1205+
}
1206+
});
1207+
return GenericArg::Const(ConstArg {
1208+
value: ct,
1209+
span: ty.span,
1210+
});
1211+
}
1212+
}
1213+
}
1214+
GenericArg::Type(self.lower_ty_direct(&ty, itctx))
1215+
}
11651216
ast::GenericArg::Const(ct) => {
11661217
GenericArg::Const(ConstArg {
11671218
value: self.lower_anon_const(&ct),

0 commit comments

Comments
 (0)