Don't manually walk through param indices when adding implicit Sized and ConstParamHasTy
This commit is contained in:
parent
361f8ba847
commit
c5d0f6c05c
@ -2205,27 +2205,7 @@ pub fn res_to_ty(
|
|||||||
err.span_note(span, format!("type parameter `{name}` defined here"));
|
err.span_note(span, format!("type parameter `{name}` defined here"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
self.hir_id_to_bound_ty(hir_id)
|
||||||
match tcx.named_bound_var(hir_id) {
|
|
||||||
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
|
|
||||||
let name =
|
|
||||||
tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local()));
|
|
||||||
let br = ty::BoundTy {
|
|
||||||
var: ty::BoundVar::from_u32(index),
|
|
||||||
kind: ty::BoundTyKind::Param(def_id, name),
|
|
||||||
};
|
|
||||||
Ty::new_bound(tcx, debruijn, br)
|
|
||||||
}
|
|
||||||
Some(rbv::ResolvedArg::EarlyBound(_)) => {
|
|
||||||
let def_id = def_id.expect_local();
|
|
||||||
let item_def_id = tcx.hir().ty_param_owner(def_id);
|
|
||||||
let generics = tcx.generics_of(item_def_id);
|
|
||||||
let index = generics.param_def_id_to_index[&def_id.to_def_id()];
|
|
||||||
Ty::new_param(tcx, index, tcx.hir().ty_param_name(def_id))
|
|
||||||
}
|
|
||||||
Some(rbv::ResolvedArg::Error(guar)) => Ty::new_error(tcx, guar),
|
|
||||||
arg => bug!("unexpected bound var resolution for {hir_id:?}: {arg:?}"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Res::SelfTyParam { .. } => {
|
Res::SelfTyParam { .. } => {
|
||||||
// `Self` in trait or type alias.
|
// `Self` in trait or type alias.
|
||||||
@ -2394,6 +2374,57 @@ pub fn res_to_ty(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Converts a hir id corresponding to a type parameter to
|
||||||
|
// a early-bound `ty::Param` or late-bound `ty::Bound`.
|
||||||
|
pub(crate) fn hir_id_to_bound_ty(&self, hir_id: hir::HirId) -> Ty<'tcx> {
|
||||||
|
let tcx = self.tcx();
|
||||||
|
match tcx.named_bound_var(hir_id) {
|
||||||
|
Some(rbv::ResolvedArg::LateBound(debruijn, index, def_id)) => {
|
||||||
|
let name = tcx.item_name(def_id);
|
||||||
|
let br = ty::BoundTy {
|
||||||
|
var: ty::BoundVar::from_u32(index),
|
||||||
|
kind: ty::BoundTyKind::Param(def_id, name),
|
||||||
|
};
|
||||||
|
Ty::new_bound(tcx, debruijn, br)
|
||||||
|
}
|
||||||
|
Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
|
||||||
|
let def_id = def_id.expect_local();
|
||||||
|
let item_def_id = tcx.hir().ty_param_owner(def_id);
|
||||||
|
let generics = tcx.generics_of(item_def_id);
|
||||||
|
let index = generics.param_def_id_to_index[&def_id.to_def_id()];
|
||||||
|
Ty::new_param(tcx, index, tcx.hir().ty_param_name(def_id))
|
||||||
|
}
|
||||||
|
Some(rbv::ResolvedArg::Error(guar)) => Ty::new_error(tcx, guar),
|
||||||
|
arg => bug!("unexpected bound var resolution for {hir_id:?}: {arg:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts a hir id corresponding to a const parameter to
|
||||||
|
// a early-bound `ConstKind::Param` or late-bound `ConstKind::Bound`.
|
||||||
|
pub(crate) fn hir_id_to_bound_const(
|
||||||
|
&self,
|
||||||
|
hir_id: hir::HirId,
|
||||||
|
param_ty: Ty<'tcx>,
|
||||||
|
) -> Const<'tcx> {
|
||||||
|
let tcx = self.tcx();
|
||||||
|
match tcx.named_bound_var(hir_id) {
|
||||||
|
Some(rbv::ResolvedArg::EarlyBound(def_id)) => {
|
||||||
|
// 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 generics = tcx.generics_of(item_def_id);
|
||||||
|
let index = generics.param_def_id_to_index[&def_id];
|
||||||
|
let name = tcx.item_name(def_id);
|
||||||
|
ty::Const::new_param(tcx, ty::ParamConst::new(index, name), param_ty)
|
||||||
|
}
|
||||||
|
Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => {
|
||||||
|
ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index), param_ty)
|
||||||
|
}
|
||||||
|
Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar, param_ty),
|
||||||
|
arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", hir_id),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Parses the programmer's textual representation of a type into our
|
/// Parses the programmer's textual representation of a type into our
|
||||||
/// internal notion of a type.
|
/// internal notion of a type.
|
||||||
pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
|
pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
|
||||||
|
@ -162,8 +162,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||||||
};
|
};
|
||||||
|
|
||||||
let generics = tcx.generics_of(def_id);
|
let generics = tcx.generics_of(def_id);
|
||||||
let parent_count = generics.parent_count as u32;
|
|
||||||
let has_own_self = generics.has_self && parent_count == 0;
|
|
||||||
|
|
||||||
// Below we'll consider the bounds on the type parameters (including `Self`)
|
// Below we'll consider the bounds on the type parameters (including `Self`)
|
||||||
// and the explicit where-clauses, but to get the full set of predicates
|
// and the explicit where-clauses, but to get the full set of predicates
|
||||||
@ -189,17 +187,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||||||
predicates.insert((trait_ref.to_predicate(tcx), tcx.def_span(def_id)));
|
predicates.insert((trait_ref.to_predicate(tcx), tcx.def_span(def_id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect the region predicates that were declared inline as
|
|
||||||
// well. In the case of parameters declared on a fn or method, we
|
|
||||||
// have to be careful to only iterate over early-bound regions.
|
|
||||||
let mut index = parent_count
|
|
||||||
+ has_own_self as u32
|
|
||||||
+ super::early_bound_lifetimes_from_generics(tcx, ast_generics).count() as u32;
|
|
||||||
|
|
||||||
trace!(?predicates);
|
|
||||||
trace!(?ast_generics);
|
|
||||||
trace!(?generics);
|
|
||||||
|
|
||||||
// Collect the predicates that were written inline by the user on each
|
// Collect the predicates that were written inline by the user on each
|
||||||
// type parameter (e.g., `<T: Foo>`). Also add `ConstArgHasType` predicates
|
// type parameter (e.g., `<T: Foo>`). Also add `ConstArgHasType` predicates
|
||||||
// for each const parameter.
|
// for each const parameter.
|
||||||
@ -208,10 +195,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||||||
// We already dealt with early bound lifetimes above.
|
// We already dealt with early bound lifetimes above.
|
||||||
GenericParamKind::Lifetime { .. } => (),
|
GenericParamKind::Lifetime { .. } => (),
|
||||||
GenericParamKind::Type { .. } => {
|
GenericParamKind::Type { .. } => {
|
||||||
let name = param.name.ident().name;
|
let param_ty = icx.astconv().hir_id_to_bound_ty(param.hir_id);
|
||||||
let param_ty = ty::ParamTy::new(index, name).to_ty(tcx);
|
|
||||||
index += 1;
|
|
||||||
|
|
||||||
let mut bounds = Bounds::default();
|
let mut bounds = Bounds::default();
|
||||||
// Params are implicitly sized unless a `?Sized` bound is found
|
// Params are implicitly sized unless a `?Sized` bound is found
|
||||||
icx.astconv().add_implicitly_sized(
|
icx.astconv().add_implicitly_sized(
|
||||||
@ -225,23 +209,16 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||||||
predicates.extend(bounds.clauses());
|
predicates.extend(bounds.clauses());
|
||||||
trace!(?predicates);
|
trace!(?predicates);
|
||||||
}
|
}
|
||||||
GenericParamKind::Const { .. } => {
|
hir::GenericParamKind::Const { .. } => {
|
||||||
let name = param.name.ident().name;
|
|
||||||
let param_const = ty::ParamConst::new(index, name);
|
|
||||||
|
|
||||||
let ct_ty = tcx
|
let ct_ty = tcx
|
||||||
.type_of(param.def_id.to_def_id())
|
.type_of(param.def_id.to_def_id())
|
||||||
.no_bound_vars()
|
.no_bound_vars()
|
||||||
.expect("const parameters cannot be generic");
|
.expect("const parameters cannot be generic");
|
||||||
|
let ct = icx.astconv().hir_id_to_bound_const(param.hir_id, ct_ty);
|
||||||
let ct = ty::Const::new_param(tcx, param_const, ct_ty);
|
|
||||||
|
|
||||||
predicates.insert((
|
predicates.insert((
|
||||||
ty::ClauseKind::ConstArgHasType(ct, ct_ty).to_predicate(tcx),
|
ty::ClauseKind::ConstArgHasType(ct, ct_ty).to_predicate(tcx),
|
||||||
param.span,
|
param.span,
|
||||||
));
|
));
|
||||||
|
|
||||||
index += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -252,8 +229,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||||||
match predicate {
|
match predicate {
|
||||||
hir::WherePredicate::BoundPredicate(bound_pred) => {
|
hir::WherePredicate::BoundPredicate(bound_pred) => {
|
||||||
let ty = icx.to_ty(bound_pred.bounded_ty);
|
let ty = icx.to_ty(bound_pred.bounded_ty);
|
||||||
let bound_vars = icx.tcx.late_bound_vars(bound_pred.hir_id);
|
let bound_vars = tcx.late_bound_vars(bound_pred.hir_id);
|
||||||
|
|
||||||
// Keep the type around in a dummy predicate, in case of no bounds.
|
// Keep the type around in a dummy predicate, in case of no bounds.
|
||||||
// That way, `where Ty:` is not a complete noop (see #53696) and `Ty`
|
// That way, `where Ty:` is not a complete noop (see #53696) and `Ty`
|
||||||
// is still checked for WF.
|
// is still checked for WF.
|
||||||
@ -296,7 +272,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
};
|
};
|
||||||
let pred = ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2))
|
let pred = ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2))
|
||||||
.to_predicate(icx.tcx);
|
.to_predicate(tcx);
|
||||||
(pred, span)
|
(pred, span)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -849,6 +849,7 @@ fn visit_fn(
|
|||||||
fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
|
fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
|
||||||
let scope = Scope::TraitRefBoundary { s: self.scope };
|
let scope = Scope::TraitRefBoundary { s: self.scope };
|
||||||
self.with(scope, |this| {
|
self.with(scope, |this| {
|
||||||
|
walk_list!(this, visit_generic_param, generics.params);
|
||||||
for param in generics.params {
|
for param in generics.params {
|
||||||
match param.kind {
|
match param.kind {
|
||||||
GenericParamKind::Lifetime { .. } => {}
|
GenericParamKind::Lifetime { .. } => {}
|
||||||
@ -865,90 +866,86 @@ fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for predicate in generics.predicates {
|
walk_list!(this, visit_where_predicate, generics.predicates);
|
||||||
match predicate {
|
})
|
||||||
&hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
|
}
|
||||||
hir_id,
|
|
||||||
bounded_ty,
|
|
||||||
bounds,
|
|
||||||
bound_generic_params,
|
|
||||||
origin,
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
|
|
||||||
bound_generic_params
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(late_bound_idx, param)| {
|
|
||||||
let pair = ResolvedArg::late(late_bound_idx as u32, param);
|
|
||||||
let r = late_arg_as_bound_arg(this.tcx, &pair.1, param);
|
|
||||||
(pair, r)
|
|
||||||
})
|
|
||||||
.unzip();
|
|
||||||
this.record_late_bound_vars(hir_id, binders.clone());
|
|
||||||
// Even if there are no lifetimes defined here, we still wrap it in a binder
|
|
||||||
// scope. If there happens to be a nested poly trait ref (an error), that
|
|
||||||
// will be `Concatenating` anyways, so we don't have to worry about the depth
|
|
||||||
// being wrong.
|
|
||||||
let scope = Scope::Binder {
|
|
||||||
hir_id,
|
|
||||||
bound_vars,
|
|
||||||
s: this.scope,
|
|
||||||
scope_type: BinderScopeType::Normal,
|
|
||||||
where_bound_origin: Some(origin),
|
|
||||||
};
|
|
||||||
this.with(scope, |this| {
|
|
||||||
this.visit_ty(&bounded_ty);
|
|
||||||
walk_list!(this, visit_param_bound, bounds);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
&hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
|
|
||||||
lifetime,
|
|
||||||
bounds,
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
this.visit_lifetime(lifetime);
|
|
||||||
walk_list!(this, visit_param_bound, bounds);
|
|
||||||
|
|
||||||
if lifetime.res != hir::LifetimeName::Static {
|
fn visit_where_predicate(&mut self, predicate: &'tcx hir::WherePredicate<'tcx>) {
|
||||||
for bound in bounds {
|
match predicate {
|
||||||
let hir::GenericBound::Outlives(lt) = bound else {
|
&hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
|
||||||
continue;
|
hir_id,
|
||||||
};
|
bounded_ty,
|
||||||
if lt.res != hir::LifetimeName::Static {
|
bounds,
|
||||||
continue;
|
bound_generic_params,
|
||||||
}
|
origin,
|
||||||
this.insert_lifetime(lt, ResolvedArg::StaticLifetime);
|
..
|
||||||
this.tcx.struct_span_lint_hir(
|
}) => {
|
||||||
lint::builtin::UNUSED_LIFETIMES,
|
let (bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) =
|
||||||
lifetime.hir_id,
|
bound_generic_params
|
||||||
lifetime.ident.span,
|
.iter()
|
||||||
format!(
|
.enumerate()
|
||||||
"unnecessary lifetime parameter `{}`",
|
.map(|(late_bound_idx, param)| {
|
||||||
lifetime.ident
|
let pair = ResolvedArg::late(late_bound_idx as u32, param);
|
||||||
),
|
let r = late_arg_as_bound_arg(self.tcx, &pair.1, param);
|
||||||
|lint| {
|
(pair, r)
|
||||||
let help = format!(
|
})
|
||||||
"you can use the `'static` lifetime directly, in place of `{}`",
|
.unzip();
|
||||||
lifetime.ident,
|
self.record_late_bound_vars(hir_id, binders.clone());
|
||||||
);
|
// Even if there are no lifetimes defined here, we still wrap it in a binder
|
||||||
lint.help(help)
|
// scope. If there happens to be a nested poly trait ref (an error), that
|
||||||
},
|
// will be `Concatenating` anyways, so we don't have to worry about the depth
|
||||||
);
|
// being wrong.
|
||||||
}
|
let scope = Scope::Binder {
|
||||||
|
hir_id,
|
||||||
|
bound_vars,
|
||||||
|
s: self.scope,
|
||||||
|
scope_type: BinderScopeType::Normal,
|
||||||
|
where_bound_origin: Some(origin),
|
||||||
|
};
|
||||||
|
self.with(scope, |this| {
|
||||||
|
walk_list!(this, visit_generic_param, bound_generic_params);
|
||||||
|
this.visit_ty(&bounded_ty);
|
||||||
|
walk_list!(this, visit_param_bound, bounds);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
&hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
|
||||||
|
lifetime,
|
||||||
|
bounds,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
|
self.visit_lifetime(lifetime);
|
||||||
|
walk_list!(self, visit_param_bound, bounds);
|
||||||
|
|
||||||
|
if lifetime.res != hir::LifetimeName::Static {
|
||||||
|
for bound in bounds {
|
||||||
|
let hir::GenericBound::Outlives(lt) = bound else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
if lt.res != hir::LifetimeName::Static {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
self.insert_lifetime(lt, ResolvedArg::StaticLifetime);
|
||||||
&hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
|
self.tcx.struct_span_lint_hir(
|
||||||
lhs_ty,
|
lint::builtin::UNUSED_LIFETIMES,
|
||||||
rhs_ty,
|
lifetime.hir_id,
|
||||||
..
|
lifetime.ident.span,
|
||||||
}) => {
|
format!("unnecessary lifetime parameter `{}`", lifetime.ident),
|
||||||
this.visit_ty(lhs_ty);
|
|lint| {
|
||||||
this.visit_ty(rhs_ty);
|
let help = format!(
|
||||||
|
"you can use the `'static` lifetime directly, in place of `{}`",
|
||||||
|
lifetime.ident,
|
||||||
|
);
|
||||||
|
lint.help(help)
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
&hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { lhs_ty, rhs_ty, .. }) => {
|
||||||
|
self.visit_ty(lhs_ty);
|
||||||
|
self.visit_ty(rhs_ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_param_bound(&mut self, bound: &'tcx hir::GenericBound<'tcx>) {
|
fn visit_param_bound(&mut self, bound: &'tcx hir::GenericBound<'tcx>) {
|
||||||
@ -986,6 +983,18 @@ fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
|
|||||||
intravisit::walk_anon_const(this, c);
|
intravisit::walk_anon_const(this, c);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_generic_param(&mut self, p: &'tcx GenericParam<'tcx>) {
|
||||||
|
match p.kind {
|
||||||
|
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
|
||||||
|
self.resolve_type_ref(p.def_id, p.hir_id);
|
||||||
|
}
|
||||||
|
GenericParamKind::Lifetime { .. } => {
|
||||||
|
// No need to resolve lifetime params, we don't use them for things
|
||||||
|
// like implicit `?Sized` or const-param-has-ty predicates.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: LocalDefId) -> ObjectLifetimeDefault {
|
fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: LocalDefId) -> ObjectLifetimeDefault {
|
||||||
|
Loading…
Reference in New Issue
Block a user