Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,7 @@ use rustc_trait_selection::traits::{
use tracing::{debug, instrument};

use crate::errors;
use crate::hir_ty_lowering::{
FeedConstTy, HirTyLowerer, InherentAssocCandidate, RegionInferReason,
};
use crate::hir_ty_lowering::{HirTyLowerer, InherentAssocCandidate, RegionInferReason};

pub(crate) mod dump;
mod generics_of;
Expand Down Expand Up @@ -1499,7 +1497,7 @@ fn const_param_default<'tcx>(

let ct = icx
.lowerer()
.lower_const_arg(default_ct, FeedConstTy::with_type_of(tcx, def_id, identity_args));
.lower_const_arg(default_ct, tcx.type_of(def_id).instantiate(tcx, identity_args));
ty::EarlyBinder::bind(ct)
}

Expand Down Expand Up @@ -1557,7 +1555,7 @@ fn const_of_item<'tcx>(
let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
let ct = icx
.lowerer()
.lower_const_arg(ct_arg, FeedConstTy::with_type_of(tcx, def_id.to_def_id(), identity_args));
.lower_const_arg(ct_arg, tcx.type_of(def_id.to_def_id()).instantiate(tcx, identity_args));
if let Err(e) = icx.check_tainted_by_errors()
&& !ct.references_error()
{
Expand Down
35 changes: 17 additions & 18 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use tracing::{debug, instrument};

use crate::errors;
use crate::hir_ty_lowering::{
AssocItemQSelf, FeedConstTy, GenericsArgsErrExtend, HirTyLowerer, ImpliedBoundsContext,
AssocItemQSelf, GenericsArgsErrExtend, HirTyLowerer, ImpliedBoundsContext,
OverlappingAsssocItemConstraints, PredicateFilter, RegionInferReason,
};

Expand Down Expand Up @@ -510,7 +510,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// Create the generic arguments for the associated type or constant by joining the
// parent arguments (the arguments of the trait) and the own arguments (the ones of
// the associated item itself) and construct an alias type using them.
let alias_term = candidate.map_bound(|trait_ref| {
candidate.map_bound(|trait_ref| {
let item_segment = hir::PathSegment {
ident: constraint.ident,
hir_id: constraint.hir_id,
Expand All @@ -528,20 +528,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
debug!(?alias_args);

ty::AliasTerm::new_from_args(tcx, assoc_item.def_id, alias_args)
});

// Provide the resolved type of the associated constant to `type_of(AnonConst)`.
if let Some(const_arg) = constraint.ct()
&& let hir::ConstArgKind::Anon(anon_const) = const_arg.kind
{
let ty = alias_term
.map_bound(|alias| tcx.type_of(alias.def_id).instantiate(tcx, alias.args));
let ty =
check_assoc_const_binding_type(self, constraint.ident, ty, constraint.hir_id);
tcx.feed_anon_const_type(anon_const.def_id, ty::EarlyBinder::bind(ty));
}

alias_term
})
};

match constraint.kind {
Expand All @@ -555,7 +542,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
hir::AssocItemConstraintKind::Equality { term } => {
let term = match term {
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
hir::Term::Const(ct) => self.lower_const_arg(ct, FeedConstTy::No).into(),
hir::Term::Const(ct) => {
let ty = projection_term.map_bound(|alias| {
tcx.type_of(alias.def_id).instantiate(tcx, alias.args)
});
let ty = check_assoc_const_binding_type(
self,
constraint.ident,
ty,
constraint.hir_id,
);

self.lower_const_arg(ct, ty).into()
}
};

// Find any late-bound regions declared in `ty` that are not
Expand Down Expand Up @@ -871,7 +870,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
/// probably gate this behind another feature flag.
///
/// [^1]: <https://github.com/rust-lang/project-const-generics/issues/28>.
fn check_assoc_const_binding_type<'tcx>(
pub(crate) fn check_assoc_const_binding_type<'tcx>(
cx: &dyn HirTyLowerer<'tcx>,
assoc_const: Ident,
ty: ty::Binder<'tcx, Ty<'tcx>>,
Expand Down
136 changes: 64 additions & 72 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,35 +253,6 @@ impl AssocItemQSelf {
}
}

/// In some cases, [`hir::ConstArg`]s that are being used in the type system
/// through const generics need to have their type "fed" to them
/// using the query system.
///
/// Use this enum with `<dyn HirTyLowerer>::lower_const_arg` to instruct it with the
/// desired behavior.
#[derive(Debug, Clone, Copy)]
pub enum FeedConstTy<'tcx> {
/// Feed the type to the (anno) const arg.
WithTy(Ty<'tcx>),
/// Don't feed the type.
No,
}

impl<'tcx> FeedConstTy<'tcx> {
/// The `DefId` belongs to the const param that we are supplying
/// this (anon) const arg to.
///
/// The list of generic args is used to instantiate the parameters
/// used by the type of the const param specified by `DefId`.
pub fn with_type_of(
tcx: TyCtxt<'tcx>,
def_id: DefId,
generic_args: &[ty::GenericArg<'tcx>],
) -> Self {
Self::WithTy(tcx.type_of(def_id).instantiate(tcx, generic_args))
}
}

#[derive(Debug, Clone, Copy)]
enum LowerTypeRelativePathMode {
Type(PermitVariants),
Expand Down Expand Up @@ -733,7 +704,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// Ambig portions of `ConstArg` are handled in the match arm below
.lower_const_arg(
ct.as_unambig_ct(),
FeedConstTy::with_type_of(tcx, param.def_id, preceding_args),
tcx.type_of(param.def_id).instantiate(tcx, preceding_args),
)
.into(),
(&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => {
Expand Down Expand Up @@ -1269,10 +1240,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let mut where_bounds = vec![];
for bound in [bound, bound2].into_iter().chain(matching_candidates) {
let bound_id = bound.def_id();
let bound_span = tcx
.associated_items(bound_id)
.find_by_ident_and_kind(tcx, assoc_ident, assoc_tag, bound_id)
.and_then(|item| tcx.hir_span_if_local(item.def_id));
let assoc_item = tcx.associated_items(bound_id).find_by_ident_and_kind(
tcx,
assoc_ident,
assoc_tag,
bound_id,
);
let bound_span = assoc_item.and_then(|item| tcx.hir_span_if_local(item.def_id));

if let Some(bound_span) = bound_span {
err.span_label(
Expand All @@ -1285,7 +1259,43 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let term: ty::Term<'_> = match term {
hir::Term::Ty(ty) => self.lower_ty(ty).into(),
hir::Term::Const(ct) => {
self.lower_const_arg(ct, FeedConstTy::No).into()
let assoc_item =
assoc_item.expect("assoc_item should be present");
let projection_term = bound.map_bound(|trait_ref| {
let item_segment = hir::PathSegment {
ident: constraint.ident,
hir_id: constraint.hir_id,
res: Res::Err,
args: Some(constraint.gen_args),
infer_args: false,
};

let alias_args = self.lower_generic_args_of_assoc_item(
constraint.ident.span,
assoc_item.def_id,
&item_segment,
trait_ref.args,
);
ty::AliasTerm::new_from_args(
tcx,
assoc_item.def_id,
alias_args,
)
});

// FIXME(mgca): code duplication with other places we lower
// the rhs' of associated const bindings
let ty = projection_term.map_bound(|alias| {
tcx.type_of(alias.def_id).instantiate(tcx, alias.args)
});
let ty = bounds::check_assoc_const_binding_type(
self,
constraint.ident,
ty,
constraint.hir_id,
);

self.lower_const_arg(ct, ty).into()
}
};
if term.references_error() {
Expand Down Expand Up @@ -2310,16 +2320,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {

/// Lower a [`hir::ConstArg`] to a (type-level) [`ty::Const`](Const).
#[instrument(skip(self), level = "debug")]
pub fn lower_const_arg(
&self,
const_arg: &hir::ConstArg<'tcx>,
feed: FeedConstTy<'tcx>,
) -> Const<'tcx> {
pub fn lower_const_arg(&self, const_arg: &hir::ConstArg<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> {
let tcx = self.tcx();

if let FeedConstTy::WithTy(anon_const_type) = feed
&& let hir::ConstArgKind::Anon(anon) = &const_arg.kind
{
if let hir::ConstArgKind::Anon(anon) = &const_arg.kind {
// FIXME(generic_const_parameter_types): Ideally we remove these errors below when
// we have the ability to intermix typeck of anon const const args with the parent
// bodies typeck.
Expand All @@ -2329,7 +2333,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// hir typeck was using equality but mir borrowck wound up using subtyping as that could
// result in a non-infer in hir typeck but a region variable in borrowck.
if tcx.features().generic_const_parameter_types()
&& (anon_const_type.has_free_regions() || anon_const_type.has_erased_regions())
&& (ty.has_free_regions() || ty.has_erased_regions())
{
let e = self.dcx().span_err(
const_arg.span,
Expand All @@ -2341,7 +2345,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// We must error if the instantiated type has any inference variables as we will
// use this type to feed the `type_of` and query results must not contain inference
// variables otherwise we will ICE.
if anon_const_type.has_non_region_infer() {
if ty.has_non_region_infer() {
let e = self.dcx().span_err(
const_arg.span,
"anonymous constants with inferred types are not yet supported",
Expand All @@ -2351,7 +2355,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
// We error when the type contains unsubstituted generics since we do not currently
// give the anon const any of the generics from the parent.
if anon_const_type.has_non_region_param() {
if ty.has_non_region_param() {
let e = self.dcx().span_err(
const_arg.span,
"anonymous constants referencing generics are not yet supported",
Expand All @@ -2360,12 +2364,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
return ty::Const::new_error(tcx, e);
}

tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(anon_const_type));
tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(ty));
}

let hir_id = const_arg.hir_id;
match const_arg.kind {
hir::ConstArgKind::Tup(exprs) => self.lower_const_arg_tup(exprs, feed, const_arg.span),
hir::ConstArgKind::Tup(exprs) => self.lower_const_arg_tup(exprs, ty, const_arg.span),
hir::ConstArgKind::Path(hir::QPath::Resolved(maybe_qself, path)) => {
debug!(?maybe_qself, ?path);
let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself));
Expand All @@ -2389,31 +2393,23 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
hir::ConstArgKind::TupleCall(qpath, args) => {
self.lower_const_arg_tuple_call(hir_id, qpath, args, const_arg.span)
}
hir::ConstArgKind::Array(array_expr) => self.lower_const_arg_array(array_expr, feed),
hir::ConstArgKind::Array(array_expr) => self.lower_const_arg_array(array_expr, ty),
hir::ConstArgKind::Anon(anon) => self.lower_const_arg_anon(anon),
hir::ConstArgKind::Infer(()) => self.ct_infer(None, const_arg.span),
hir::ConstArgKind::Error(e) => ty::Const::new_error(tcx, e),
hir::ConstArgKind::Literal(kind) if let FeedConstTy::WithTy(anon_const_type) = feed => {
self.lower_const_arg_literal(&kind, anon_const_type, const_arg.span)
}
hir::ConstArgKind::Literal(..) => {
let e = self.dcx().span_err(const_arg.span, "literal of unknown type");
ty::Const::new_error(tcx, e)
hir::ConstArgKind::Literal(kind) => {
self.lower_const_arg_literal(&kind, ty, const_arg.span)
}
}
}

fn lower_const_arg_array(
&self,
array_expr: &'tcx hir::ConstArgArrayExpr<'tcx>,
feed: FeedConstTy<'tcx>,
ty: Ty<'tcx>,
) -> Const<'tcx> {
let tcx = self.tcx();

let FeedConstTy::WithTy(ty) = feed else {
return Const::new_error_with_message(tcx, array_expr.span, "unsupported const array");
};

let ty::Array(elem_ty, _) = ty.kind() else {
return Const::new_error_with_message(
tcx,
Expand All @@ -2425,7 +2421,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let elems = array_expr
.elems
.iter()
.map(|elem| self.lower_const_arg(elem, FeedConstTy::WithTy(*elem_ty)))
.map(|elem| self.lower_const_arg(elem, *elem_ty))
.collect::<Vec<_>>();

let valtree = ty::ValTree::from_branches(tcx, elems);
Expand Down Expand Up @@ -2508,7 +2504,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
.iter()
.zip(args)
.map(|(field_def, arg)| {
self.lower_const_arg(arg, FeedConstTy::with_type_of(tcx, field_def.did, adt_args))
self.lower_const_arg(arg, tcx.type_of(field_def.did).instantiate(tcx, adt_args))
})
.collect::<Vec<_>>();

Expand All @@ -2527,15 +2523,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
fn lower_const_arg_tup(
&self,
exprs: &'tcx [&'tcx hir::ConstArg<'tcx>],
feed: FeedConstTy<'tcx>,
ty: Ty<'tcx>,
span: Span,
) -> Const<'tcx> {
let tcx = self.tcx();

let FeedConstTy::WithTy(ty) = feed else {
return Const::new_error_with_message(tcx, span, "const tuple lack type information");
};

let ty::Tuple(tys) = ty.kind() else {
let e = tcx.dcx().span_err(span, format!("expected `{}`, found const tuple", ty));
return Const::new_error(tcx, e);
Expand All @@ -2544,7 +2536,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let exprs = exprs
.iter()
.zip(tys.iter())
.map(|(expr, ty)| self.lower_const_arg(expr, FeedConstTy::WithTy(ty)))
.map(|(expr, ty)| self.lower_const_arg(expr, ty))
.collect::<Vec<_>>();

let valtree = ty::ValTree::from_branches(tcx, exprs);
Expand Down Expand Up @@ -2631,7 +2623,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {

self.lower_const_arg(
expr.expr,
FeedConstTy::with_type_of(tcx, field_def.did, adt_args),
tcx.type_of(field_def.did).instantiate(tcx, adt_args),
)
}
None => {
Expand Down Expand Up @@ -2993,7 +2985,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
.unwrap_or_else(|guar| Ty::new_error(tcx, guar))
}
hir::TyKind::Array(ty, length) => {
let length = self.lower_const_arg(length, FeedConstTy::No);
let length = self.lower_const_arg(length, tcx.types.usize);
Ty::new_array_with_const_len(tcx, self.lower_ty(ty), length)
}
hir::TyKind::Infer(()) => {
Expand Down Expand Up @@ -3033,8 +3025,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// Keep this list of types in sync with the list of types that
// the `RangePattern` trait is implemented for.
ty::Int(_) | ty::Uint(_) | ty::Char => {
let start = self.lower_const_arg(start, FeedConstTy::No);
let end = self.lower_const_arg(end, FeedConstTy::No);
let start = self.lower_const_arg(start, ty);
let end = self.lower_const_arg(end, ty);
Ok(ty::PatternKind::Range { start, end })
}
_ => Err(self
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ use rustc_span::{ErrorGuaranteed, Span};
use rustc_trait_selection::traits;

pub use crate::collect::suggest_impl_trait;
use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer};
use crate::hir_ty_lowering::HirTyLowerer;

rustc_fluent_macro::fluent_messages! { "../messages.ftl" }

Expand Down Expand Up @@ -301,8 +301,8 @@ pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
pub fn lower_const_arg_for_rustdoc<'tcx>(
tcx: TyCtxt<'tcx>,
hir_ct: &hir::ConstArg<'tcx>,
feed: FeedConstTy<'tcx>,
ty: Ty<'tcx>,
) -> Const<'tcx> {
let env_def_id = tcx.hir_get_parent_item(hir_ct.hir_id);
collect::ItemCtxt::new(tcx, env_def_id.def_id).lowerer().lower_const_arg(hir_ct, feed)
collect::ItemCtxt::new(tcx, env_def_id.def_id).lowerer().lower_const_arg(hir_ct, ty)
}
Loading
Loading