Skip to content

Commit 1494041

Browse files
committed
Fix handling of const qpath args
1 parent 08fd782 commit 1494041

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
@@ -1095,7 +1095,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
10951095
{
10961096
if !res.matches_ns(Namespace::TypeNS)
10971097
// FIXME: should this only allow single-segment paths?
1098-
&& path.is_potential_trivial_const_arg(self.tcx.features().min_generic_const_args())
1098+
&& path.is_potential_trivial_const_arg(&None, self.tcx.features().min_generic_const_args())
10991099
{
11001100
debug!(
11011101
"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,

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

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

16471647
/// Lower a qualified path to a type.
16481648
#[instrument(level = "debug", skip_all)]
1649-
fn lower_qpath(
1649+
fn lower_qpath_ty(
16501650
&self,
16511651
span: Span,
16521652
opt_self_ty: Option<Ty<'tcx>>,
@@ -1664,14 +1664,64 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
16641664
};
16651665
debug!(?self_ty);
16661666

1667+
let (item_def_id, item_args) = self.lower_qpath_shared(
1668+
span,
1669+
self_ty,
1670+
trait_def_id,
1671+
item_def_id,
1672+
trait_segment,
1673+
item_segment,
1674+
);
1675+
Ty::new_projection_from_args(tcx, item_def_id, item_args)
1676+
}
1677+
1678+
/// Lower a qualified path to a const.
1679+
#[instrument(level = "debug", skip_all)]
1680+
fn lower_qpath_const(
1681+
&self,
1682+
span: Span,
1683+
self_ty: Ty<'tcx>,
1684+
item_def_id: DefId,
1685+
trait_segment: &hir::PathSegment<'tcx>,
1686+
item_segment: &hir::PathSegment<'tcx>,
1687+
) -> Const<'tcx> {
1688+
let tcx = self.tcx();
1689+
1690+
let trait_def_id = tcx.parent(item_def_id);
1691+
debug!(?trait_def_id);
1692+
1693+
debug!(?self_ty);
1694+
1695+
let (item_def_id, item_args) = self.lower_qpath_shared(
1696+
span,
1697+
self_ty,
1698+
trait_def_id,
1699+
item_def_id,
1700+
trait_segment,
1701+
item_segment,
1702+
);
1703+
let uv = ty::UnevaluatedConst::new(item_def_id, item_args);
1704+
Const::new_unevaluated(tcx, uv)
1705+
}
1706+
1707+
#[instrument(level = "debug", skip_all)]
1708+
fn lower_qpath_shared(
1709+
&self,
1710+
span: Span,
1711+
self_ty: Ty<'tcx>,
1712+
trait_def_id: DefId,
1713+
item_def_id: DefId,
1714+
trait_segment: &hir::PathSegment<'tcx>,
1715+
item_segment: &hir::PathSegment<'tcx>,
1716+
) -> (DefId, GenericArgsRef<'tcx>) {
16671717
let trait_ref =
16681718
self.lower_mono_trait_ref(span, trait_def_id, self_ty, trait_segment, false);
16691719
debug!(?trait_ref);
16701720

16711721
let item_args =
16721722
self.lower_generic_args_of_assoc_item(span, item_def_id, item_segment, trait_ref.args);
16731723

1674-
Ty::new_projection_from_args(tcx, item_def_id, item_args)
1724+
(item_def_id, item_args)
16751725
}
16761726

16771727
fn error_missing_qpath_self_ty(
@@ -2021,7 +2071,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
20212071
path.segments[..path.segments.len() - 2].iter(),
20222072
GenericsArgsErrExtend::None,
20232073
);
2024-
self.lower_qpath(
2074+
self.lower_qpath_ty(
20252075
span,
20262076
opt_self_ty,
20272077
def_id,
@@ -2222,6 +2272,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
22222272
);
22232273
ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args))
22242274
}
2275+
Res::Def(DefKind::AssocConst, did) => {
2276+
debug_assert!(path.segments.len() >= 2);
2277+
let _ = self.prohibit_generic_args(
2278+
path.segments[..path.segments.len() - 2].iter(),
2279+
GenericsArgsErrExtend::None,
2280+
);
2281+
// FIXME(mgca): maybe needs proper error reported
2282+
let Some(self_ty) = opt_self_ty else { span_bug!(span, "{path:?}") };
2283+
self.lower_qpath_const(
2284+
span,
2285+
self_ty,
2286+
did,
2287+
&path.segments[path.segments.len() - 2],
2288+
path.segments.last().unwrap(),
2289+
)
2290+
}
22252291
Res::Def(DefKind::Static { .. }, _) => {
22262292
span_bug!(span, "use of bare `static` ConstArgKind::Path's not yet supported")
22272293
}
@@ -2238,7 +2304,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
22382304

22392305
// Exhaustive match to be clear about what exactly we're considering to be
22402306
// an invalid Res for a const path.
2241-
Res::Def(
2307+
res @ (Res::Def(
22422308
DefKind::Mod
22432309
| DefKind::Enum
22442310
| DefKind::Variant
@@ -2252,7 +2318,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
22522318
| DefKind::Union
22532319
| DefKind::Trait
22542320
| DefKind::ForeignTy
2255-
| DefKind::AssocConst
22562321
| DefKind::TyParam
22572322
| DefKind::Macro(_)
22582323
| DefKind::LifetimeParam
@@ -2275,7 +2340,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
22752340
| Res::Local(_)
22762341
| Res::ToolMod
22772342
| Res::NonMacroAttr(_)
2278-
| Res::Err => Const::new_error_with_message(tcx, span, "invalid Res for const path"),
2343+
| Res::Err) => Const::new_error_with_message(
2344+
tcx,
2345+
span,
2346+
format!("invalid Res {res:?} for const path"),
2347+
),
22792348
}
22802349
}
22812350

compiler/rustc_resolve/src/late.rs

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

0 commit comments

Comments
 (0)