Rollup merge of #138284 - compiler-errors:const-param-ty-annotation, r=BoxyUwU
Do not write user type annotation for const param value path As I noted in the code comment, `DefKind::ConstParam` isn't actually *generic* over its own args, we just use the identity args from the body when lowering the value path so we have something to plug into the `EarlyBinder` we get back from `type_of` for the const param. So skip over it in `write_user_type_annotation_from_args`. Somewhat unrelated, but I left an explanation for a somewhat mysterious quirk in the THIR lowering of user type annotations for patterns having to do with ctors and their `type_of` not actually being the type of the pattern node it's ascribing. Fixes #138048 r? ``@BoxyUwU``
This commit is contained in:
commit
16ff824133
7 changed files with 51 additions and 11 deletions
|
|
@ -220,6 +220,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
) {
|
||||
debug!("fcx {}", self.tag());
|
||||
|
||||
// Don't write user type annotations for const param types, since we give them
|
||||
// identity args just so that we can trivially substitute their `EarlyBinder`.
|
||||
// We enforce that they match their type in MIR later on.
|
||||
if matches!(self.tcx.def_kind(def_id), DefKind::ConstParam) {
|
||||
return;
|
||||
}
|
||||
|
||||
if Self::can_contain_user_lifetime_bounds((args, user_self_ty)) {
|
||||
let canonicalized = self.canonicalize_user_type_annotation(ty::UserType::new(
|
||||
ty::UserTypeKind::TypeOf(def_id, UserArgs { args, user_self_ty }),
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ impl<'tcx> ThirBuildCx<'tcx> {
|
|||
&self,
|
||||
hir_id: HirId,
|
||||
) -> Option<ty::CanonicalUserType<'tcx>> {
|
||||
crate::thir::util::user_args_applied_to_ty_of_hir_id(self.typeck_results, hir_id)
|
||||
crate::thir::util::user_args_applied_to_ty_of_hir_id(self.tcx, self.typeck_results, hir_id)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -539,7 +539,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
|
|||
&self,
|
||||
hir_id: hir::HirId,
|
||||
) -> Option<ty::CanonicalUserType<'tcx>> {
|
||||
crate::thir::util::user_args_applied_to_ty_of_hir_id(self.typeck_results, hir_id)
|
||||
crate::thir::util::user_args_applied_to_ty_of_hir_id(self.tcx, self.typeck_results, hir_id)
|
||||
}
|
||||
|
||||
/// Takes a HIR Path. If the path is a constant, evaluates it and feeds
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
use std::assert_matches::assert_matches;
|
||||
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::{self, CanonicalUserType};
|
||||
use rustc_middle::ty::{self, CanonicalUserType, TyCtxt};
|
||||
use tracing::debug;
|
||||
|
||||
/// Looks up the type associated with this hir-id and applies the
|
||||
/// user-given generic parameters; the hir-id must map to a suitable
|
||||
/// type.
|
||||
pub(crate) fn user_args_applied_to_ty_of_hir_id<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
typeck_results: &ty::TypeckResults<'tcx>,
|
||||
hir_id: hir::HirId,
|
||||
) -> Option<CanonicalUserType<'tcx>> {
|
||||
|
|
@ -16,7 +20,23 @@ pub(crate) fn user_args_applied_to_ty_of_hir_id<'tcx>(
|
|||
let ty = typeck_results.node_type(hir_id);
|
||||
match ty.kind() {
|
||||
ty::Adt(adt_def, ..) => {
|
||||
// This "fixes" user type annotations for tupled ctor patterns for ADTs.
|
||||
// That's because `type_of(ctor_did)` returns a FnDef, but we actually
|
||||
// want to be annotating the type of the ADT itself. It's a bit goofy,
|
||||
// but it's easier to adjust this here rather than in the path lowering
|
||||
// code for patterns in HIR.
|
||||
if let ty::UserTypeKind::TypeOf(did, _) = &mut user_ty.value.kind {
|
||||
// This is either already set up correctly (struct, union, enum, or variant),
|
||||
// or needs adjusting (ctor). Make sure we don't start adjusting other
|
||||
// user annotations like consts or fn calls.
|
||||
assert_matches!(
|
||||
tcx.def_kind(*did),
|
||||
DefKind::Ctor(..)
|
||||
| DefKind::Struct
|
||||
| DefKind::Enum
|
||||
| DefKind::Union
|
||||
| DefKind::Variant
|
||||
);
|
||||
*did = adt_def.did();
|
||||
}
|
||||
Some(user_ty)
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
//@ known-bug: #138048
|
||||
struct Foo;
|
||||
|
||||
impl<'b> Foo {
|
||||
fn bar<const V: u8>() {
|
||||
let V;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
struct Foo<'a>(&'a ());
|
||||
|
||||
// We need a lifetime in scope or else we do not write a user type annotation as a fast-path.
|
||||
impl<'a> Foo<'a> {
|
||||
fn bar<const V: u8>() {
|
||||
let V;
|
||||
//~^ ERROR constant parameters cannot be referenced in patterns
|
||||
}
|
||||
}
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
error[E0158]: constant parameters cannot be referenced in patterns
|
||||
--> $DIR/bad-param-in-pat.rs:6:13
|
||||
|
|
||||
LL | fn bar<const V: u8>() {
|
||||
| ----------- constant defined here
|
||||
LL | let V;
|
||||
| ^ can't be used in patterns
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0158`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue