mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-21 22:34:05 +00:00
Simplify some places that deal with generic parameter defaults
This commit is contained in:
parent
143ce0920a
commit
d0ddba3d5b
@ -1427,16 +1427,6 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
|
|||||||
let predicates = tcx.predicates_of(def_id.to_def_id());
|
let predicates = tcx.predicates_of(def_id.to_def_id());
|
||||||
let generics = tcx.generics_of(def_id);
|
let generics = tcx.generics_of(def_id);
|
||||||
|
|
||||||
let is_our_default = |def: &ty::GenericParamDef| match def.kind {
|
|
||||||
GenericParamDefKind::Type { has_default, .. }
|
|
||||||
| GenericParamDefKind::Const { has_default, .. } => {
|
|
||||||
has_default && def.index >= generics.parent_count as u32
|
|
||||||
}
|
|
||||||
GenericParamDefKind::Lifetime => {
|
|
||||||
span_bug!(tcx.def_span(def.def_id), "lifetime params can have no default")
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check that concrete defaults are well-formed. See test `type-check-defaults.rs`.
|
// Check that concrete defaults are well-formed. See test `type-check-defaults.rs`.
|
||||||
// For example, this forbids the declaration:
|
// For example, this forbids the declaration:
|
||||||
//
|
//
|
||||||
@ -1444,42 +1434,23 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
|
|||||||
//
|
//
|
||||||
// Here, the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.
|
// Here, the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.
|
||||||
for param in &generics.own_params {
|
for param in &generics.own_params {
|
||||||
match param.kind {
|
if let Some(default) = param.default_value(tcx).map(ty::EarlyBinder::instantiate_identity) {
|
||||||
GenericParamDefKind::Type { .. } => {
|
|
||||||
if is_our_default(param) {
|
|
||||||
let ty = tcx.type_of(param.def_id).instantiate_identity();
|
|
||||||
// Ignore dependent defaults -- that is, where the default of one type
|
// Ignore dependent defaults -- that is, where the default of one type
|
||||||
// parameter includes another (e.g., `<T, U = T>`). In those cases, we can't
|
// parameter includes another (e.g., `<T, U = T>`). In those cases, we can't
|
||||||
// be sure if it will error or not as user might always specify the other.
|
// be sure if it will error or not as user might always specify the other.
|
||||||
if !ty.has_param() {
|
// FIXME(generic_const_exprs): This is incorrect when dealing with unused const params.
|
||||||
|
// E.g: `struct Foo<const N: usize, const M: usize = { 1 - 2 }>;`. Here, we should
|
||||||
|
// eagerly error but we don't as we have `ConstKind::Unevaluated(.., [N, M])`.
|
||||||
|
if !default.has_param() {
|
||||||
wfcx.register_wf_obligation(
|
wfcx.register_wf_obligation(
|
||||||
tcx.def_span(param.def_id),
|
tcx.def_span(param.def_id),
|
||||||
Some(WellFormedLoc::Ty(param.def_id.expect_local())),
|
matches!(param.kind, GenericParamDefKind::Type { .. })
|
||||||
ty.into(),
|
.then(|| WellFormedLoc::Ty(param.def_id.expect_local())),
|
||||||
|
default,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GenericParamDefKind::Const { .. } => {
|
|
||||||
if is_our_default(param) {
|
|
||||||
// FIXME(const_generics_defaults): This
|
|
||||||
// is incorrect when dealing with unused args, for example
|
|
||||||
// for `struct Foo<const N: usize, const M: usize = { 1 - 2 }>`
|
|
||||||
// we should eagerly error.
|
|
||||||
let default_ct = tcx.const_param_default(param.def_id).instantiate_identity();
|
|
||||||
if !default_ct.has_param() {
|
|
||||||
wfcx.register_wf_obligation(
|
|
||||||
tcx.def_span(param.def_id),
|
|
||||||
None,
|
|
||||||
default_ct.into(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Doesn't have defaults.
|
|
||||||
GenericParamDefKind::Lifetime => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that trait predicates are WF when params are instantiated with their defaults.
|
// Check that trait predicates are WF when params are instantiated with their defaults.
|
||||||
// We don't want to overly constrain the predicates that may be written but we want to
|
// We don't want to overly constrain the predicates that may be written but we want to
|
||||||
@ -1490,39 +1461,16 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
|
|||||||
//
|
//
|
||||||
// First we build the defaulted generic parameters.
|
// First we build the defaulted generic parameters.
|
||||||
let args = GenericArgs::for_item(tcx, def_id.to_def_id(), |param, _| {
|
let args = GenericArgs::for_item(tcx, def_id.to_def_id(), |param, _| {
|
||||||
match param.kind {
|
if param.index >= generics.parent_count as u32
|
||||||
GenericParamDefKind::Lifetime => {
|
|
||||||
// All regions are identity.
|
|
||||||
tcx.mk_param_from_def(param)
|
|
||||||
}
|
|
||||||
|
|
||||||
GenericParamDefKind::Type { .. } => {
|
|
||||||
// If the param has a default, ...
|
// If the param has a default, ...
|
||||||
if is_our_default(param) {
|
&& let Some(default) = param.default_value(tcx).map(ty::EarlyBinder::instantiate_identity)
|
||||||
let default_ty = tcx.type_of(param.def_id).instantiate_identity();
|
|
||||||
// ... and it's not a dependent default, ...
|
// ... and it's not a dependent default, ...
|
||||||
if !default_ty.has_param() {
|
&& !default.has_param()
|
||||||
|
{
|
||||||
// ... then instantiate it with the default.
|
// ... then instantiate it with the default.
|
||||||
return default_ty.into();
|
return default;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
tcx.mk_param_from_def(param)
|
tcx.mk_param_from_def(param)
|
||||||
}
|
|
||||||
GenericParamDefKind::Const { .. } => {
|
|
||||||
// If the param has a default, ...
|
|
||||||
if is_our_default(param) {
|
|
||||||
let default_ct = tcx.const_param_default(param.def_id).instantiate_identity();
|
|
||||||
// ... and it's not a dependent default, ...
|
|
||||||
if !default_ct.has_param() {
|
|
||||||
// ... then instantiate it with the default.
|
|
||||||
return default_ct.into();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tcx.mk_param_from_def(param)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Now we build the instantiated predicates.
|
// Now we build the instantiated predicates.
|
||||||
|
@ -1306,33 +1306,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
rustc_hir_analysis::hir_ty_lowering::RegionInferReason::Param(param),
|
rustc_hir_analysis::hir_ty_lowering::RegionInferReason::Param(param),
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
GenericParamDefKind::Type { has_default, .. } => {
|
GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
|
||||||
if !infer_args && has_default {
|
if !infer_args && let Some(default) = param.default_value(tcx) {
|
||||||
// If we have a default, then it doesn't matter that we're not
|
// If we have a default, then it doesn't matter that we're not inferring
|
||||||
// inferring the type arguments: we provide the default where any
|
// the type/const arguments: We provide the default where any is missing.
|
||||||
// is missing.
|
return default.instantiate(tcx, preceding_args);
|
||||||
tcx.type_of(param.def_id).instantiate(tcx, preceding_args).into()
|
}
|
||||||
} else {
|
// If no type/const arguments were provided, we have to infer them.
|
||||||
// If no type arguments were provided, we have to infer them.
|
// This case also occurs as a result of some malformed input, e.g.,
|
||||||
// This case also occurs as a result of some malformed input, e.g.
|
// a lifetime argument being given instead of a type/const parameter.
|
||||||
// a lifetime argument being given instead of a type parameter.
|
|
||||||
// Using inference instead of `Error` gives better error messages.
|
// Using inference instead of `Error` gives better error messages.
|
||||||
self.fcx.var_for_def(self.span, param)
|
self.fcx.var_for_def(self.span, param)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GenericParamDefKind::Const { has_default, .. } => {
|
|
||||||
if has_default {
|
|
||||||
if !infer_args {
|
|
||||||
return tcx
|
|
||||||
.const_param_default(param.def_id)
|
|
||||||
.instantiate(tcx, preceding_args)
|
|
||||||
.into();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.fcx.var_for_def(self.span, param)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,10 +86,10 @@ impl GenericParamDef {
|
|||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
) -> Option<EarlyBinder<'tcx, ty::GenericArg<'tcx>>> {
|
) -> Option<EarlyBinder<'tcx, ty::GenericArg<'tcx>>> {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
GenericParamDefKind::Type { has_default, .. } if has_default => {
|
GenericParamDefKind::Type { has_default: true, .. } => {
|
||||||
Some(tcx.type_of(self.def_id).map_bound(|t| t.into()))
|
Some(tcx.type_of(self.def_id).map_bound(|t| t.into()))
|
||||||
}
|
}
|
||||||
GenericParamDefKind::Const { has_default, .. } if has_default => {
|
GenericParamDefKind::Const { has_default: true, .. } => {
|
||||||
Some(tcx.const_param_default(self.def_id).map_bound(|c| c.into()))
|
Some(tcx.const_param_default(self.def_id).map_bound(|c| c.into()))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -782,21 +782,11 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
|
|||||||
impl ReachEverythingInTheInterfaceVisitor<'_, '_> {
|
impl ReachEverythingInTheInterfaceVisitor<'_, '_> {
|
||||||
fn generics(&mut self) -> &mut Self {
|
fn generics(&mut self) -> &mut Self {
|
||||||
for param in &self.ev.tcx.generics_of(self.item_def_id).own_params {
|
for param in &self.ev.tcx.generics_of(self.item_def_id).own_params {
|
||||||
match param.kind {
|
if let GenericParamDefKind::Const { .. } = param.kind {
|
||||||
GenericParamDefKind::Lifetime => {}
|
|
||||||
GenericParamDefKind::Type { has_default, .. } => {
|
|
||||||
if has_default {
|
|
||||||
self.visit(self.ev.tcx.type_of(param.def_id).instantiate_identity());
|
self.visit(self.ev.tcx.type_of(param.def_id).instantiate_identity());
|
||||||
}
|
}
|
||||||
}
|
if let Some(default) = param.default_value(self.ev.tcx) {
|
||||||
GenericParamDefKind::Const { has_default, .. } => {
|
self.visit(default.instantiate_identity());
|
||||||
self.visit(self.ev.tcx.type_of(param.def_id).instantiate_identity());
|
|
||||||
if has_default {
|
|
||||||
self.visit(
|
|
||||||
self.ev.tcx.const_param_default(param.def_id).instantiate_identity(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
|
Loading…
Reference in New Issue
Block a user