Skip to content

Commit 764e46b

Browse files
committed
Fix handling of const qpath args
1 parent 59c7938 commit 764e46b

File tree

4 files changed

+95
-17
lines changed

4 files changed

+95
-17
lines changed

compiler/rustc_ast/src/util/const_args.rs

Lines changed: 14 additions & 5 deletions
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
}

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,7 +1108,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
11081108
{
11091109
if !res.matches_ns(Namespace::TypeNS)
11101110
// FIXME: should this only allow single-segment paths?
1111-
&& path.is_potential_trivial_const_arg(self.tcx.features().min_generic_const_args())
1111+
&& path.is_potential_trivial_const_arg(&None, self.tcx.features().min_generic_const_args())
11121112
{
11131113
debug!(
11141114
"lower_generic_arg: Lowering type argument as const argument: {:?}",
@@ -2074,7 +2074,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
20742074
let tcx = self.tcx;
20752075

20762076
let ct_kind = if path
2077-
.is_potential_trivial_const_arg(tcx.features().min_generic_const_args())
2077+
.is_potential_trivial_const_arg(&None, tcx.features().min_generic_const_args())
20782078
&& (tcx.features().min_generic_const_args()
20792079
|| matches!(res, Res::Def(DefKind::ConstParam, _)))
20802080
{
@@ -2148,14 +2148,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
21482148
};
21492149
let maybe_res =
21502150
self.resolver.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res());
2151-
if let ExprKind::Path(None, path) = &expr.kind
2152-
&& path.is_potential_trivial_const_arg(tcx.features().min_generic_const_args())
2151+
if let ExprKind::Path(qself, path) = &expr.kind
2152+
&& path.is_potential_trivial_const_arg(qself, tcx.features().min_generic_const_args())
21532153
&& (tcx.features().min_generic_const_args()
21542154
|| matches!(maybe_res, Some(Res::Def(DefKind::ConstParam, _))))
21552155
{
21562156
let qpath = self.lower_qpath(
21572157
expr.id,
2158-
&None,
2158+
qself,
21592159
path,
21602160
ParamMode::Optional,
21612161
AllowReturnTypeNotation::No,

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1624,7 +1624,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
16241624

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

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

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

1652-
Ty::new_projection_from_args(tcx, item_def_id, item_args)
1702+
(item_def_id, item_args)
16531703
}
16541704

16551705
fn error_missing_qpath_self_ty(
@@ -2000,7 +2050,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
20002050
path.segments[..path.segments.len() - 2].iter(),
20012051
GenericsArgsErrExtend::None,
20022052
);
2003-
self.lower_qpath(
2053+
self.lower_qpath_ty(
20042054
span,
20052055
opt_self_ty,
20062056
def_id,
@@ -2165,6 +2215,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
21652215
);
21662216
ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args))
21672217
}
2218+
Res::Def(DefKind::AssocConst, did) => {
2219+
debug_assert!(path.segments.len() >= 2);
2220+
let _ = self.prohibit_generic_args(
2221+
path.segments[..path.segments.len() - 2].iter(),
2222+
GenericsArgsErrExtend::None,
2223+
);
2224+
// FIXME(mgca): maybe needs proper error reported
2225+
let Some(self_ty) = opt_self_ty else { span_bug!(span, "{path:?}") };
2226+
self.lower_qpath_const(
2227+
span,
2228+
self_ty,
2229+
did,
2230+
&path.segments[path.segments.len() - 2],
2231+
path.segments.last().unwrap(),
2232+
)
2233+
}
21682234
Res::Def(DefKind::Static { .. }, _) => {
21692235
span_bug!(span, "use of bare `static` ConstArgKind::Path's not yet supported")
21702236
}
@@ -2177,7 +2243,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
21772243

21782244
// Exhaustive match to be clear about what exactly we're considering to be
21792245
// an invalid Res for a const path.
2180-
Res::Def(
2246+
res @ (Res::Def(
21812247
DefKind::Mod
21822248
| DefKind::Enum
21832249
| DefKind::Variant
@@ -2191,7 +2257,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
21912257
| DefKind::Union
21922258
| DefKind::Trait
21932259
| DefKind::ForeignTy
2194-
| DefKind::AssocConst
21952260
| DefKind::TyParam
21962261
| DefKind::Macro(_)
21972262
| DefKind::LifetimeParam
@@ -2214,7 +2279,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
22142279
| Res::Local(_)
22152280
| Res::ToolMod
22162281
| Res::NonMacroAttr(_)
2217-
| Res::Err => Const::new_error_with_message(tcx, span, "invalid Res for const path"),
2282+
| Res::Err) => Const::new_error_with_message(
2283+
tcx,
2284+
span,
2285+
format!("invalid Res {res:?} for const path"),
2286+
),
22182287
}
22192288
}
22202289

compiler/rustc_resolve/src/late.rs

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

0 commit comments

Comments
 (0)