Don't try and handle unfed type_of
on anon consts
This commit is contained in:
parent
c44b3d50fe
commit
ec036cda3f
6 changed files with 14 additions and 270 deletions
|
@ -309,10 +309,10 @@ impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
|
||||||
self.tcx.ensure().type_of(param.def_id);
|
self.tcx.ensure().type_of(param.def_id);
|
||||||
if let Some(default) = default {
|
if let Some(default) = default {
|
||||||
// need to store default and type of default
|
// need to store default and type of default
|
||||||
|
self.tcx.ensure().const_param_default(param.def_id);
|
||||||
if let hir::ConstArgKind::Anon(ac) = default.kind {
|
if let hir::ConstArgKind::Anon(ac) = default.kind {
|
||||||
self.tcx.ensure().type_of(ac.def_id);
|
self.tcx.ensure().type_of(ac.def_id);
|
||||||
}
|
}
|
||||||
self.tcx.ensure().const_param_default(param.def_id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1817,7 +1817,6 @@ fn const_param_default<'tcx>(
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
let icx = ItemCtxt::new(tcx, def_id);
|
let icx = ItemCtxt::new(tcx, def_id);
|
||||||
// FIXME(const_generics): investigate which places do and don't need const ty feeding
|
let ct = icx.lowerer().lower_const_arg(default_ct, FeedConstTy::Param(def_id.to_def_id()));
|
||||||
let ct = icx.lowerer().lower_const_arg(default_ct, FeedConstTy::No);
|
|
||||||
ty::EarlyBinder::bind(ct)
|
ty::EarlyBinder::bind(ct)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,6 @@ use rustc_middle::ty::{self, Article, IsSuggestable, Ty, TyCtxt, TypeVisitableEx
|
||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_span::symbol::Ident;
|
use rustc_span::symbol::Ident;
|
||||||
use rustc_span::{DUMMY_SP, Span};
|
use rustc_span::{DUMMY_SP, Span};
|
||||||
use tracing::debug;
|
|
||||||
|
|
||||||
use super::{ItemCtxt, bad_placeholder};
|
use super::{ItemCtxt, bad_placeholder};
|
||||||
use crate::errors::TypeofReservedKeywordUsed;
|
use crate::errors::TypeofReservedKeywordUsed;
|
||||||
|
@ -138,252 +137,26 @@ fn const_arg_anon_type_of<'tcx>(tcx: TyCtxt<'tcx>, arg_hir_id: HirId, span: Span
|
||||||
use hir::*;
|
use hir::*;
|
||||||
use rustc_middle::ty::Ty;
|
use rustc_middle::ty::Ty;
|
||||||
|
|
||||||
let parent_node_id = tcx.parent_hir_id(arg_hir_id);
|
match tcx.parent_hir_node(arg_hir_id) {
|
||||||
let parent_node = tcx.hir_node(parent_node_id);
|
// Array length const arguments do not have `type_of` fed as there is never a corresponding
|
||||||
|
// generic parameter definition.
|
||||||
let (generics, arg_idx) = match parent_node {
|
|
||||||
// Easy case: arrays repeat expressions.
|
|
||||||
Node::Ty(&hir::Ty { kind: TyKind::Array(_, ref constant), .. })
|
Node::Ty(&hir::Ty { kind: TyKind::Array(_, ref constant), .. })
|
||||||
| Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
|
| Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
|
||||||
if constant.hir_id == arg_hir_id =>
|
if constant.hir_id == arg_hir_id =>
|
||||||
{
|
{
|
||||||
return tcx.types.usize;
|
return tcx.types.usize;
|
||||||
}
|
}
|
||||||
Node::GenericParam(&GenericParam {
|
|
||||||
def_id: param_def_id,
|
|
||||||
kind: GenericParamKind::Const { default: Some(ct), .. },
|
|
||||||
..
|
|
||||||
}) if ct.hir_id == arg_hir_id => {
|
|
||||||
return tcx
|
|
||||||
.type_of(param_def_id)
|
|
||||||
.no_bound_vars()
|
|
||||||
.expect("const parameter types cannot be generic");
|
|
||||||
}
|
|
||||||
|
|
||||||
// This match arm is for when the def_id appears in a GAT whose
|
// This is not a `bug!` as const arguments in path segments that did not resolve to anything
|
||||||
// path can't be resolved without typechecking e.g.
|
// will result in `type_of` never being fed.
|
||||||
//
|
_ => Ty::new_error_with_message(
|
||||||
// trait Foo {
|
|
||||||
// type Assoc<const N: usize>;
|
|
||||||
// fn foo() -> Self::Assoc<3>;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// In the above code we would call this query with the def_id of 3 and
|
|
||||||
// the parent_node we match on would be the hir node for Self::Assoc<3>
|
|
||||||
//
|
|
||||||
// `Self::Assoc<3>` cant be resolved without typechecking here as we
|
|
||||||
// didnt write <Self as Foo>::Assoc<3>. If we did then another match
|
|
||||||
// arm would handle this.
|
|
||||||
//
|
|
||||||
// I believe this match arm is only needed for GAT but I am not 100% sure - BoxyUwU
|
|
||||||
Node::Ty(hir_ty @ hir::Ty { kind: TyKind::Path(QPath::TypeRelative(ty, segment)), .. }) => {
|
|
||||||
// Find the Item containing the associated type so we can create an ItemCtxt.
|
|
||||||
// Using the ItemCtxt lower the HIR for the unresolved assoc type into a
|
|
||||||
// ty which is a fully resolved projection.
|
|
||||||
// For the code example above, this would mean lowering `Self::Assoc<3>`
|
|
||||||
// to a ty::Alias(ty::Projection, `<Self as Foo>::Assoc<3>`).
|
|
||||||
let item_def_id = tcx.hir().get_parent_item(ty.hir_id).def_id;
|
|
||||||
let ty = ItemCtxt::new(tcx, item_def_id).lower_ty(hir_ty);
|
|
||||||
|
|
||||||
// Iterate through the generics of the projection to find the one that corresponds to
|
|
||||||
// the def_id that this query was called with. We filter to only type and const args here
|
|
||||||
// as a precaution for if it's ever allowed to elide lifetimes in GAT's. It currently isn't
|
|
||||||
// but it can't hurt to be safe ^^
|
|
||||||
if let ty::Alias(ty::Projection | ty::Inherent, projection) = ty.kind() {
|
|
||||||
let generics = tcx.generics_of(projection.def_id);
|
|
||||||
|
|
||||||
let arg_index = segment
|
|
||||||
.args
|
|
||||||
.and_then(|args| {
|
|
||||||
args.args
|
|
||||||
.iter()
|
|
||||||
.filter(|arg| arg.is_ty_or_const())
|
|
||||||
.position(|arg| arg.hir_id() == arg_hir_id)
|
|
||||||
})
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
bug!("no arg matching AnonConst in segment");
|
|
||||||
});
|
|
||||||
|
|
||||||
(generics, arg_index)
|
|
||||||
} else {
|
|
||||||
// I dont think it's possible to reach this but I'm not 100% sure - BoxyUwU
|
|
||||||
return Ty::new_error_with_message(
|
|
||||||
tcx,
|
|
||||||
span,
|
|
||||||
"unexpected non-GAT usage of an anon const",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Node::Expr(&Expr {
|
|
||||||
kind:
|
|
||||||
ExprKind::MethodCall(segment, ..) | ExprKind::Path(QPath::TypeRelative(_, segment)),
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
let body_owner = tcx.hir().enclosing_body_owner(arg_hir_id);
|
|
||||||
let tables = tcx.typeck(body_owner);
|
|
||||||
// This may fail in case the method/path does not actually exist.
|
|
||||||
// As there is no relevant param for `def_id`, we simply return
|
|
||||||
// `None` here.
|
|
||||||
let Some(type_dependent_def) = tables.type_dependent_def_id(parent_node_id) else {
|
|
||||||
return Ty::new_error_with_message(
|
|
||||||
tcx,
|
|
||||||
span,
|
|
||||||
format!("unable to find type-dependent def for {parent_node_id:?}"),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
let idx = segment
|
|
||||||
.args
|
|
||||||
.and_then(|args| {
|
|
||||||
args.args
|
|
||||||
.iter()
|
|
||||||
.filter(|arg| arg.is_ty_or_const())
|
|
||||||
.position(|arg| arg.hir_id() == arg_hir_id)
|
|
||||||
})
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
bug!("no arg matching ConstArg in segment");
|
|
||||||
});
|
|
||||||
|
|
||||||
(tcx.generics_of(type_dependent_def), idx)
|
|
||||||
}
|
|
||||||
|
|
||||||
Node::Ty(&hir::Ty { kind: TyKind::Path(_), .. })
|
|
||||||
| Node::Expr(&Expr { kind: ExprKind::Path(_) | ExprKind::Struct(..), .. })
|
|
||||||
| Node::TraitRef(..)
|
|
||||||
| Node::Pat(_) => {
|
|
||||||
let path = match parent_node {
|
|
||||||
Node::Ty(&hir::Ty { kind: TyKind::Path(QPath::Resolved(_, path)), .. })
|
|
||||||
| Node::TraitRef(&TraitRef { path, .. }) => &*path,
|
|
||||||
Node::Expr(&Expr {
|
|
||||||
kind:
|
|
||||||
ExprKind::Path(QPath::Resolved(_, path))
|
|
||||||
| ExprKind::Struct(&QPath::Resolved(_, path), ..),
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
let body_owner = tcx.hir().enclosing_body_owner(arg_hir_id);
|
|
||||||
let _tables = tcx.typeck(body_owner);
|
|
||||||
&*path
|
|
||||||
}
|
|
||||||
Node::Pat(pat) => {
|
|
||||||
if let Some(path) = get_path_containing_arg_in_pat(pat, arg_hir_id) {
|
|
||||||
path
|
|
||||||
} else {
|
|
||||||
return Ty::new_error_with_message(
|
|
||||||
tcx,
|
|
||||||
span,
|
|
||||||
format!("unable to find const parent for {arg_hir_id} in pat {pat:?}"),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
return Ty::new_error_with_message(
|
|
||||||
tcx,
|
|
||||||
span,
|
|
||||||
format!("unexpected const parent path {parent_node:?}"),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// We've encountered an `AnonConst` in some path, so we need to
|
|
||||||
// figure out which generic parameter it corresponds to and return
|
|
||||||
// the relevant type.
|
|
||||||
let Some((arg_index, segment)) = path.segments.iter().find_map(|seg| {
|
|
||||||
let args = seg.args?;
|
|
||||||
args.args
|
|
||||||
.iter()
|
|
||||||
.filter(|arg| arg.is_ty_or_const())
|
|
||||||
.position(|arg| arg.hir_id() == arg_hir_id)
|
|
||||||
.map(|index| (index, seg))
|
|
||||||
.or_else(|| {
|
|
||||||
args.constraints
|
|
||||||
.iter()
|
|
||||||
.copied()
|
|
||||||
.filter_map(AssocItemConstraint::ct)
|
|
||||||
.position(|ct| ct.hir_id == arg_hir_id)
|
|
||||||
.map(|idx| (idx, seg))
|
|
||||||
})
|
|
||||||
}) else {
|
|
||||||
return Ty::new_error_with_message(tcx, span, "no arg matching AnonConst in path");
|
|
||||||
};
|
|
||||||
|
|
||||||
let generics = match tcx.res_generics_def_id(segment.res) {
|
|
||||||
Some(def_id) => tcx.generics_of(def_id),
|
|
||||||
None => {
|
|
||||||
return Ty::new_error_with_message(
|
|
||||||
tcx,
|
|
||||||
span,
|
|
||||||
format!("unexpected anon const res {:?} in path: {:?}", segment.res, path),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
(generics, arg_index)
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => {
|
|
||||||
return Ty::new_error_with_message(
|
|
||||||
tcx,
|
|
||||||
span,
|
|
||||||
format!("unexpected const arg parent in type_of(): {parent_node:?}"),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
debug!(?parent_node);
|
|
||||||
debug!(?generics, ?arg_idx);
|
|
||||||
if let Some(param_def_id) = generics
|
|
||||||
.own_params
|
|
||||||
.iter()
|
|
||||||
.filter(|param| param.kind.is_ty_or_const())
|
|
||||||
.nth(match generics.has_self && generics.parent.is_none() {
|
|
||||||
true => arg_idx + 1,
|
|
||||||
false => arg_idx,
|
|
||||||
})
|
|
||||||
.and_then(|param| match param.kind {
|
|
||||||
ty::GenericParamDefKind::Const { .. } => {
|
|
||||||
debug!(?param);
|
|
||||||
Some(param.def_id)
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
{
|
|
||||||
tcx.type_of(param_def_id).no_bound_vars().expect("const parameter types cannot be generic")
|
|
||||||
} else {
|
|
||||||
return Ty::new_error_with_message(
|
|
||||||
tcx,
|
tcx,
|
||||||
span,
|
span,
|
||||||
format!("const generic parameter not found in {generics:?} at position {arg_idx:?}"),
|
"`type_of` called on const argument's anon const before the const argument was lowered",
|
||||||
);
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_path_containing_arg_in_pat<'hir>(
|
|
||||||
pat: &'hir hir::Pat<'hir>,
|
|
||||||
arg_id: HirId,
|
|
||||||
) -> Option<&'hir hir::Path<'hir>> {
|
|
||||||
use hir::*;
|
|
||||||
|
|
||||||
let is_arg_in_path = |p: &hir::Path<'_>| {
|
|
||||||
p.segments
|
|
||||||
.iter()
|
|
||||||
.filter_map(|seg| seg.args)
|
|
||||||
.flat_map(|args| args.args)
|
|
||||||
.any(|arg| arg.hir_id() == arg_id)
|
|
||||||
};
|
|
||||||
let mut arg_path = None;
|
|
||||||
pat.walk(|pat| match pat.kind {
|
|
||||||
PatKind::Struct(QPath::Resolved(_, path), _, _)
|
|
||||||
| PatKind::TupleStruct(QPath::Resolved(_, path), _, _)
|
|
||||||
| PatKind::Path(QPath::Resolved(_, path))
|
|
||||||
if is_arg_in_path(path) =>
|
|
||||||
{
|
|
||||||
arg_path = Some(path);
|
|
||||||
false
|
|
||||||
}
|
|
||||||
_ => true,
|
|
||||||
});
|
|
||||||
arg_path
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, Ty<'_>> {
|
pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, Ty<'_>> {
|
||||||
use rustc_hir::*;
|
use rustc_hir::*;
|
||||||
use rustc_middle::ty::Ty;
|
use rustc_middle::ty::Ty;
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
trait X {
|
trait X {
|
||||||
fn test() -> Self::Assoc<{ async {} }>;
|
fn test() -> Self::Assoc<{ async {} }>;
|
||||||
//~^ ERROR associated type `Assoc` not found for `Self`
|
//~^ ERROR associated type `Assoc` not found for `Self`
|
||||||
//~| ERROR associated type `Assoc` not found for `Self`
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() {}
|
pub fn main() {}
|
||||||
|
|
|
@ -4,14 +4,6 @@ error[E0220]: associated type `Assoc` not found for `Self`
|
||||||
LL | fn test() -> Self::Assoc<{ async {} }>;
|
LL | fn test() -> Self::Assoc<{ async {} }>;
|
||||||
| ^^^^^ associated type `Assoc` not found
|
| ^^^^^ associated type `Assoc` not found
|
||||||
|
|
||||||
error[E0220]: associated type `Assoc` not found for `Self`
|
error: aborting due to 1 previous error
|
||||||
--> $DIR/coroutine-in-orphaned-anon-const.rs:4:24
|
|
||||||
|
|
|
||||||
LL | fn test() -> Self::Assoc<{ async {} }>;
|
|
||||||
| ^^^^^ associated type `Assoc` not found
|
|
||||||
|
|
|
||||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0220`.
|
For more information about this error, try `rustc --explain E0220`.
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
trait X {
|
trait X {
|
||||||
fn a<T>() -> T::unknown<{}> {}
|
fn a<T>() -> T::unknown<{}> {}
|
||||||
//~^ ERROR: associated type `unknown` not found for `T`
|
//~^ ERROR: associated type `unknown` not found for `T`
|
||||||
//~| ERROR: associated type `unknown` not found for `T`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Y {
|
trait Y {
|
||||||
|
@ -14,7 +13,6 @@ trait Y {
|
||||||
trait Z<T> {
|
trait Z<T> {
|
||||||
fn a() -> T::unknown<{}> {}
|
fn a() -> T::unknown<{}> {}
|
||||||
//~^ ERROR: associated type `unknown` not found for `T`
|
//~^ ERROR: associated type `unknown` not found for `T`
|
||||||
//~| ERROR: associated type `unknown` not found for `T`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -5,34 +5,18 @@ LL | fn a<T>() -> T::unknown<{}> {}
|
||||||
| ^^^^^^^ associated type `unknown` not found
|
| ^^^^^^^ associated type `unknown` not found
|
||||||
|
|
||||||
error[E0220]: associated type `unknown` not found for `T`
|
error[E0220]: associated type `unknown` not found for `T`
|
||||||
--> $DIR/unknown-assoc-with-const-arg.rs:15:18
|
--> $DIR/unknown-assoc-with-const-arg.rs:14:18
|
||||||
|
|
|
|
||||||
LL | fn a() -> T::unknown<{}> {}
|
LL | fn a() -> T::unknown<{}> {}
|
||||||
| ^^^^^^^ associated type `unknown` not found
|
| ^^^^^^^ associated type `unknown` not found
|
||||||
|
|
||||||
error[E0220]: associated type `unknown` not found for `T`
|
|
||||||
--> $DIR/unknown-assoc-with-const-arg.rs:4:21
|
|
||||||
|
|
|
||||||
LL | fn a<T>() -> T::unknown<{}> {}
|
|
||||||
| ^^^^^^^ associated type `unknown` not found
|
|
||||||
|
|
|
||||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
|
||||||
|
|
||||||
error[E0220]: associated type `unknown` not found for `T`
|
|
||||||
--> $DIR/unknown-assoc-with-const-arg.rs:15:18
|
|
||||||
|
|
|
||||||
LL | fn a() -> T::unknown<{}> {}
|
|
||||||
| ^^^^^^^ associated type `unknown` not found
|
|
||||||
|
|
|
||||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
|
||||||
|
|
||||||
error[E0433]: failed to resolve: use of undeclared type `NOT_EXIST`
|
error[E0433]: failed to resolve: use of undeclared type `NOT_EXIST`
|
||||||
--> $DIR/unknown-assoc-with-const-arg.rs:10:15
|
--> $DIR/unknown-assoc-with-const-arg.rs:9:15
|
||||||
|
|
|
|
||||||
LL | fn a() -> NOT_EXIST::unknown<{}> {}
|
LL | fn a() -> NOT_EXIST::unknown<{}> {}
|
||||||
| ^^^^^^^^^ use of undeclared type `NOT_EXIST`
|
| ^^^^^^^^^ use of undeclared type `NOT_EXIST`
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0220, E0433.
|
Some errors have detailed explanations: E0220, E0433.
|
||||||
For more information about an error, try `rustc --explain E0220`.
|
For more information about an error, try `rustc --explain E0220`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue