Skip to content

Commit a5a9370

Browse files
committed
Fix handling of const qpath args
1 parent 8ffa35c commit a5a9370

File tree

4 files changed

+95
-17
lines changed

4 files changed

+95
-17
lines changed

Diff for: compiler/rustc_ast/src/util/const_args.rs

+14-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use std::ops::ControlFlow;
22

3+
use crate::ptr::P;
34
use crate::visit::{Visitor, walk_anon_const};
4-
use crate::{DUMMY_NODE_ID, Expr, ExprKind, Path};
5+
use crate::{DUMMY_NODE_ID, Expr, ExprKind, Path, QSelf};
56

67
impl Expr {
78
// FIXME: update docs
@@ -18,7 +19,7 @@ impl Expr {
1819
MGCATrivialConstArgVisitor::new().visit_expr(this).is_continue()
1920
} else {
2021
if let ExprKind::Path(None, path) = &this.kind
21-
&& path.is_potential_trivial_const_arg(allow_mgca_arg)
22+
&& path.is_potential_trivial_const_arg(&None, allow_mgca_arg)
2223
{
2324
true
2425
} else {
@@ -31,11 +32,19 @@ impl Expr {
3132
impl Path {
3233
// FIXME: add docs
3334
#[tracing::instrument(level = "debug", ret)]
34-
pub fn is_potential_trivial_const_arg(&self, allow_mgca_arg: bool) -> bool {
35+
pub fn is_potential_trivial_const_arg(
36+
&self,
37+
qself: &Option<P<QSelf>>,
38+
allow_mgca_arg: bool,
39+
) -> bool {
3540
if allow_mgca_arg {
36-
MGCATrivialConstArgVisitor::new().visit_path(self, DUMMY_NODE_ID).is_continue()
41+
let mut visitor = MGCATrivialConstArgVisitor::new();
42+
visitor.visit_qself(qself).is_continue()
43+
&& visitor.visit_path(self, DUMMY_NODE_ID).is_continue()
3744
} else {
38-
self.segments.len() == 1 && self.segments.iter().all(|seg| seg.args.is_none())
45+
qself.is_none()
46+
&& self.segments.len() == 1
47+
&& self.segments.iter().all(|seg| seg.args.is_none())
3948
}
4049
}
4150
}

Diff for: compiler/rustc_ast_lowering/src/lib.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1102,7 +1102,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
11021102
{
11031103
if !res.matches_ns(Namespace::TypeNS)
11041104
// FIXME: should this only allow single-segment paths?
1105-
&& path.is_potential_trivial_const_arg(self.tcx.features().min_generic_const_args())
1105+
&& path.is_potential_trivial_const_arg(&None, self.tcx.features().min_generic_const_args())
11061106
{
11071107
debug!(
11081108
"lower_generic_arg: Lowering type argument as const argument: {:?}",
@@ -2063,7 +2063,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
20632063
let tcx = self.tcx;
20642064

20652065
let ct_kind = if path
2066-
.is_potential_trivial_const_arg(tcx.features().min_generic_const_args())
2066+
.is_potential_trivial_const_arg(&None, tcx.features().min_generic_const_args())
20672067
&& (tcx.features().min_generic_const_args()
20682068
|| matches!(res, Res::Def(DefKind::ConstParam, _)))
20692069
{
@@ -2137,14 +2137,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
21372137
};
21382138
let maybe_res =
21392139
self.resolver.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res());
2140-
if let ExprKind::Path(None, path) = &expr.kind
2141-
&& path.is_potential_trivial_const_arg(tcx.features().min_generic_const_args())
2140+
if let ExprKind::Path(qself, path) = &expr.kind
2141+
&& path.is_potential_trivial_const_arg(qself, tcx.features().min_generic_const_args())
21422142
&& (tcx.features().min_generic_const_args()
21432143
|| matches!(maybe_res, Some(Res::Def(DefKind::ConstParam, _))))
21442144
{
21452145
let qpath = self.lower_qpath(
21462146
expr.id,
2147-
&None,
2147+
qself,
21482148
path,
21492149
ParamMode::Optional,
21502150
AllowReturnTypeNotation::No,

Diff for: compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+75-6
Original file line numberDiff line numberDiff line change
@@ -1623,7 +1623,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
16231623

16241624
/// Lower a qualified path to a type.
16251625
#[instrument(level = "debug", skip_all)]
1626-
fn lower_qpath(
1626+
fn lower_qpath_ty(
16271627
&self,
16281628
span: Span,
16291629
opt_self_ty: Option<Ty<'tcx>>,
@@ -1641,14 +1641,64 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
16411641
};
16421642
debug!(?self_ty);
16431643

1644+
let (item_def_id, item_args) = self.lower_qpath_shared(
1645+
span,
1646+
self_ty,
1647+
trait_def_id,
1648+
item_def_id,
1649+
trait_segment,
1650+
item_segment,
1651+
);
1652+
Ty::new_projection_from_args(tcx, item_def_id, item_args)
1653+
}
1654+
1655+
/// Lower a qualified path to a const.
1656+
#[instrument(level = "debug", skip_all)]
1657+
fn lower_qpath_const(
1658+
&self,
1659+
span: Span,
1660+
self_ty: Ty<'tcx>,
1661+
item_def_id: DefId,
1662+
trait_segment: &hir::PathSegment<'tcx>,
1663+
item_segment: &hir::PathSegment<'tcx>,
1664+
) -> Const<'tcx> {
1665+
let tcx = self.tcx();
1666+
1667+
let trait_def_id = tcx.parent(item_def_id);
1668+
debug!(?trait_def_id);
1669+
1670+
debug!(?self_ty);
1671+
1672+
let (item_def_id, item_args) = self.lower_qpath_shared(
1673+
span,
1674+
self_ty,
1675+
trait_def_id,
1676+
item_def_id,
1677+
trait_segment,
1678+
item_segment,
1679+
);
1680+
let uv = ty::UnevaluatedConst::new(item_def_id, item_args);
1681+
Const::new_unevaluated(tcx, uv)
1682+
}
1683+
1684+
#[instrument(level = "debug", skip_all)]
1685+
fn lower_qpath_shared(
1686+
&self,
1687+
span: Span,
1688+
self_ty: Ty<'tcx>,
1689+
trait_def_id: DefId,
1690+
item_def_id: DefId,
1691+
trait_segment: &hir::PathSegment<'tcx>,
1692+
item_segment: &hir::PathSegment<'tcx>,
1693+
) -> (DefId, GenericArgsRef<'tcx>) {
16441694
let trait_ref =
16451695
self.lower_mono_trait_ref(span, trait_def_id, self_ty, trait_segment, false);
16461696
debug!(?trait_ref);
16471697

16481698
let item_args =
16491699
self.lower_generic_args_of_assoc_item(span, item_def_id, item_segment, trait_ref.args);
16501700

1651-
Ty::new_projection_from_args(tcx, item_def_id, item_args)
1701+
(item_def_id, item_args)
16521702
}
16531703

16541704
fn error_missing_qpath_self_ty(
@@ -1999,7 +2049,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
19992049
path.segments[..path.segments.len() - 2].iter(),
20002050
GenericsArgsErrExtend::None,
20012051
);
2002-
self.lower_qpath(
2052+
self.lower_qpath_ty(
20032053
span,
20042054
opt_self_ty,
20052055
def_id,
@@ -2164,6 +2214,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
21642214
);
21652215
ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args))
21662216
}
2217+
Res::Def(DefKind::AssocConst, did) => {
2218+
debug_assert!(path.segments.len() >= 2);
2219+
let _ = self.prohibit_generic_args(
2220+
path.segments[..path.segments.len() - 2].iter(),
2221+
GenericsArgsErrExtend::None,
2222+
);
2223+
// FIXME(mgca): maybe needs proper error reported
2224+
let Some(self_ty) = opt_self_ty else { span_bug!(span, "{path:?}") };
2225+
self.lower_qpath_const(
2226+
span,
2227+
self_ty,
2228+
did,
2229+
&path.segments[path.segments.len() - 2],
2230+
path.segments.last().unwrap(),
2231+
)
2232+
}
21672233
Res::Def(DefKind::Static { .. }, _) => {
21682234
span_bug!(span, "use of bare `static` ConstArgKind::Path's not yet supported")
21692235
}
@@ -2176,7 +2242,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
21762242

21772243
// Exhaustive match to be clear about what exactly we're considering to be
21782244
// an invalid Res for a const path.
2179-
Res::Def(
2245+
res @ (Res::Def(
21802246
DefKind::Mod
21812247
| DefKind::Enum
21822248
| DefKind::Variant
@@ -2190,7 +2256,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
21902256
| DefKind::Union
21912257
| DefKind::Trait
21922258
| DefKind::ForeignTy
2193-
| DefKind::AssocConst
21942259
| DefKind::TyParam
21952260
| DefKind::Macro(_)
21962261
| DefKind::LifetimeParam
@@ -2213,7 +2278,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
22132278
| Res::Local(_)
22142279
| Res::ToolMod
22152280
| Res::NonMacroAttr(_)
2216-
| Res::Err => Const::new_error_with_message(tcx, span, "invalid Res for const path"),
2281+
| Res::Err) => Const::new_error_with_message(
2282+
tcx,
2283+
span,
2284+
format!("invalid Res {res:?} for const path"),
2285+
),
22172286
}
22182287
}
22192288

Diff for: compiler/rustc_resolve/src/late.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1185,7 +1185,7 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
11851185
if let TyKind::Path(None, ref path) = ty.kind {
11861186
// We cannot disambiguate multi-segment paths right now as that requires type
11871187
// checking.
1188-
if path.is_potential_trivial_const_arg(false) {
1188+
if path.is_potential_trivial_const_arg(&None, false) {
11891189
let mut check_ns = |ns| {
11901190
self.maybe_resolve_ident_in_lexical_scope(path.segments[0].ident, ns)
11911191
.is_some()

0 commit comments

Comments
 (0)