Skip to content

Commit

Permalink
Begin to use ConstArgKind::Path for all paths, not just params
Browse files Browse the repository at this point in the history
  • Loading branch information
camelid committed Oct 1, 2024
1 parent c87004a commit 2b73426
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 133 deletions.
57 changes: 10 additions & 47 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2357,53 +2357,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ty_id: NodeId,
span: Span,
) -> &'hir hir::ConstArg<'hir> {
let ct_kind = match res {
Res::Def(DefKind::ConstParam, _) => {
let qpath = self.lower_qpath(
ty_id,
&None,
path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
hir::ConstArgKind::Path(qpath)
}
_ => {
// Construct an AnonConst where the expr is the "ty"'s path.

let parent_def_id = self.current_def_id_parent;
let node_id = self.next_node_id();
let span = self.lower_span(span);

// Add a definition for the in-band const def.
let def_id =
self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, span);
let hir_id = self.lower_node_id(node_id);

let path_expr = Expr {
id: ty_id,
kind: ExprKind::Path(None, path.clone()),
span,
attrs: AttrVec::new(),
tokens: None,
};

let ct = self.with_new_scopes(span, |this| {
self.arena.alloc(hir::AnonConst {
def_id,
hir_id,
body: this.with_def_id_parent(def_id, |this| {
this.lower_const_body(path_expr.span, Some(&path_expr))
}),
span,
})
});
hir::ConstArgKind::Anon(ct)
}
};

let qpath = self.lower_qpath(
ty_id,
&None,
path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
);
let ct_kind = hir::ConstArgKind::Path(qpath);
self.arena.alloc(hir::ConstArg {
hir_id: self.next_id(),
kind: ct_kind,
Expand Down
59 changes: 35 additions & 24 deletions compiler/rustc_middle/src/ty/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,10 +215,7 @@ impl<'tcx> Const<'tcx> {
}

match const_arg.kind {
hir::ConstArgKind::Path(qpath) => {
// FIXME(min_generic_const_args): for now only params are lowered to ConstArgKind::Path
Self::from_param(tcx, qpath, const_arg.hir_id)
}
hir::ConstArgKind::Path(qpath) => Self::from_path(tcx, qpath, const_arg.hir_id),
hir::ConstArgKind::Anon(anon) => Self::from_anon_const(tcx, anon.def_id),
}
}
Expand All @@ -240,7 +237,7 @@ impl<'tcx> Const<'tcx> {

let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");

match Self::try_from_lit_or_param(tcx, ty, expr) {
match Self::try_from_lit(tcx, ty, expr) {
Some(v) => v,
None => ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst {
def: def.to_def_id(),
Expand All @@ -249,40 +246,54 @@ impl<'tcx> Const<'tcx> {
}
}

/// Lower a const param to a [`Const`].
///
/// IMPORTANT: `qpath` must be a const param, otherwise this will panic
fn from_param(tcx: TyCtxt<'tcx>, qpath: hir::QPath<'tcx>, hir_id: HirId) -> Self {
let hir::QPath::Resolved(_, &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. }) =
qpath
else {
span_bug!(qpath.span(), "non-param {qpath:?} passed to Const::from_param")
};
fn from_path(tcx: TyCtxt<'tcx>, qpath: hir::QPath<'tcx>, hir_id: HirId) -> Self {
match qpath {
hir::QPath::Resolved(_, &path) => match path.res {
Res::Def(DefKind::ConstParam, def_id) => Self::from_param(tcx, def_id, hir_id),
Res::Def(DefKind::Const, def_id) => {
// FIXME: support parametrized consts (instead of empty list).
let uv = ty::UnevaluatedConst::new(def_id, ty::List::empty());
Self::new_unevaluated(tcx, uv)
}
r => Self::new_error(
tcx,
tcx.dcx().span_delayed_bug(
tcx.hir().span(hir_id),
format!("Const::from_path: invalid qpath res: {r:?}"),
),
),
},
hir::QPath::TypeRelative(..) => todo!("associated const paths"),
// FIXME: use span_delayed_bug?
hir::QPath::LangItem(..) => span_bug!(
tcx.hir().span(hir_id),
"Const::from_path: invalid qpath provided: {qpath:?}"
),
}
}

match tcx.named_bound_var(hir_id) {
/// Lower a const param to a [`Const`]. This is only meant as a helper for [`Self::from_path`].
fn from_param(tcx: TyCtxt<'tcx>, param_def_id: DefId, path_hir_id: HirId) -> Self {
match tcx.named_bound_var(path_hir_id) {
Some(rbv::ResolvedArg::EarlyBound(_)) => {
// Find the name and index of the const parameter by indexing the generics of
// the parent item and construct a `ParamConst`.
let item_def_id = tcx.parent(def_id);
let item_def_id = tcx.parent(param_def_id);
let generics = tcx.generics_of(item_def_id);
let index = generics.param_def_id_to_index[&def_id];
let name = tcx.item_name(def_id);
let index = generics.param_def_id_to_index[&param_def_id];
let name = tcx.item_name(param_def_id);
ty::Const::new_param(tcx, ty::ParamConst::new(index, name))
}
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index))
}
Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar),
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", hir_id),
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", path_hir_id),
}
}

#[instrument(skip(tcx), level = "debug")]
fn try_from_lit_or_param(
tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>,
expr: &'tcx hir::Expr<'tcx>,
) -> Option<Self> {
fn try_from_lit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>) -> Option<Self> {
// Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
// currently have to be wrapped in curly brackets, so it's necessary to special-case.
let expr = match &expr.kind {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,7 @@ LL | let _ = Checked::<{ generic_arg::<u32> }>;
= note: expected fn pointer `fn(usize) -> _`
found fn item `fn(u32) -> _ {generic_arg::<u32>}`

error[E0282]: type annotations needed
--> $DIR/fn-const-param-infer.rs:35:23
|
LL | let _ = Checked::<generic>;
| ^^^^^^^ cannot infer type of the type parameter `T` declared on the function `generic`
|
help: consider specifying the generic argument
|
LL | let _ = Checked::<generic::<T>>;
| +++++

error: aborting due to 3 previous errors
error: aborting due to 2 previous errors

Some errors have detailed explanations: E0282, E0308, E0741.
For more information about an error, try `rustc --explain E0282`.
Some errors have detailed explanations: E0308, E0741.
For more information about an error, try `rustc --explain E0308`.
17 changes: 3 additions & 14 deletions tests/ui/const-generics/fn-const-param-infer.full.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,7 @@ LL | let _ = Checked::<{ generic_arg::<u32> }>;
= note: expected fn pointer `fn(usize) -> _`
found fn item `fn(u32) -> _ {generic_arg::<u32>}`

error[E0282]: type annotations needed
--> $DIR/fn-const-param-infer.rs:35:23
|
LL | let _ = Checked::<generic>;
| ^^^^^^^ cannot infer type of the type parameter `T` declared on the function `generic`
|
help: consider specifying the generic argument
|
LL | let _ = Checked::<generic::<T>>;
| +++++

error: aborting due to 3 previous errors
error: aborting due to 2 previous errors

Some errors have detailed explanations: E0282, E0308, E0741.
For more information about an error, try `rustc --explain E0282`.
Some errors have detailed explanations: E0308, E0741.
For more information about an error, try `rustc --explain E0308`.
16 changes: 2 additions & 14 deletions tests/ui/const-generics/fn-const-param-infer.min.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,6 @@ LL | let _ = Checked::<{ generic_arg::<u32> }>;
= note: expected fn pointer `fn(usize) -> _`
found fn item `fn(u32) -> _ {generic_arg::<u32>}`

error[E0282]: type annotations needed
--> $DIR/fn-const-param-infer.rs:35:23
|
LL | let _ = Checked::<generic>;
| ^^^^^^^ cannot infer type of the type parameter `T` declared on the function `generic`
|
help: consider specifying the generic argument
|
LL | let _ = Checked::<generic::<T>>;
| +++++

error: aborting due to 3 previous errors
error: aborting due to 2 previous errors

Some errors have detailed explanations: E0282, E0308.
For more information about an error, try `rustc --explain E0282`.
For more information about this error, try `rustc --explain E0308`.
Original file line number Diff line number Diff line change
Expand Up @@ -72,17 +72,17 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more
LL + #![feature(adt_const_params)]
|

error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
--> $DIR/unevaluated-const-ice-119731.rs:27:37
error: maximum number of nodes exceeded in constant v20::v2
--> $DIR/unevaluated-const-ice-119731.rs:11:5
|
LL | impl<const v10: usize> v17<v10, v2> {
| ^^
LL | const v2: v11 = [[256; v4]; v4];
| ^^^^^^^^^^^^^

error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
--> $DIR/unevaluated-const-ice-119731.rs:27:37
error: maximum number of nodes exceeded in constant v20::v2
--> $DIR/unevaluated-const-ice-119731.rs:11:5
|
LL | impl<const v10: usize> v17<v10, v2> {
| ^^
LL | const v2: v11 = [[256; v4]; v4];
| ^^^^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

Expand Down
53 changes: 44 additions & 9 deletions tests/ui/const-generics/opaque_types2.stderr
Original file line number Diff line number Diff line change
@@ -1,15 +1,50 @@
error[E0308]: mismatched types
--> $DIR/opaque_types2.rs:13:11
error[E0391]: cycle detected when computing type of `Foo::{opaque#0}`
--> $DIR/opaque_types2.rs:3:12
|
LL | type Foo = impl Sized;
| ---------- the found opaque type
...
LL | foo::<C>();
| ^ expected `u32`, found opaque type
| ^^^^^^^^^^
|
= note: expected type `u32`
found opaque type `Foo`
note: ...which requires computing type of opaque `Foo::{opaque#0}`...
--> $DIR/opaque_types2.rs:3:12
|
LL | type Foo = impl Sized;
| ^^^^^^^^^^
note: ...which requires type-checking `bar`...
--> $DIR/opaque_types2.rs:9:1
|
LL | / fn bar()
LL | | where
LL | | Foo:,
| |_________^
note: ...which requires evaluating type-level constant...
--> $DIR/opaque_types2.rs:7:1
|
LL | const C: Foo = 42;
| ^^^^^^^^^^^^
note: ...which requires const-evaluating + checking `C`...
--> $DIR/opaque_types2.rs:7:1
|
LL | const C: Foo = 42;
| ^^^^^^^^^^^^
note: ...which requires caching mir of `C` for CTFE...
--> $DIR/opaque_types2.rs:7:1
|
LL | const C: Foo = 42;
| ^^^^^^^^^^^^
note: ...which requires elaborating drops for `C`...
--> $DIR/opaque_types2.rs:7:1
|
LL | const C: Foo = 42;
| ^^^^^^^^^^^^
= note: ...which requires normalizing `Foo`...
= note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle
note: cycle used when checking that `Foo::{opaque#0}` is well-formed
--> $DIR/opaque_types2.rs:3:12
|
LL | type Foo = impl Sized;
| ^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0308`.
For more information about this error, try `rustc --explain E0391`.
3 changes: 0 additions & 3 deletions tests/ui/generics/generic-function-item-where-type.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ error[E0747]: constant provided when a type was expected
|
LL | foo::<main>()
| ^^^^
|
= help: `main` is a function item, not a type
= help: function item types cannot be named directly

error: aborting due to 1 previous error

Expand Down

0 comments on commit 2b73426

Please sign in to comment.