Skip to content

Commit

Permalink
Fix inner ty check
Browse files Browse the repository at this point in the history
  • Loading branch information
sjwang05 committed Jan 28, 2024
1 parent 8095dd6 commit 486c90d
Show file tree
Hide file tree
Showing 10 changed files with 288 additions and 174 deletions.
8 changes: 5 additions & 3 deletions compiler/rustc_hir_analysis/messages.ftl
Expand Up @@ -80,12 +80,14 @@ hir_analysis_const_impl_for_non_const_trait =
hir_analysis_const_param_ty_impl_on_infringing_inner_ty =
the trait `ConstParamTy` cannot be implemented for this type
.label = this {$def_descr} does not implement `ConstParamTy`
.suggestion = consider annotating this {$def_descr} with `#[derive(ConstParamTy)]`
.label = this type does not implement `ConstParamTy`
hir_analysis_const_param_ty_impl_on_infringing_inner_ty_sugg =
consider annotating with `#[derive(ConstParamTy)]`
hir_analysis_const_param_ty_impl_on_non_adt =
the trait `ConstParamTy` may not be implemented for this type
.label = type is not a structure or enumeration
.label = the type `{$ty}` is not a structure or enumeration
hir_analysis_const_specialize = cannot specialize on const impl with non-const impl
Expand Down
47 changes: 22 additions & 25 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Expand Up @@ -939,6 +939,22 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
Ok(())
})
} else {
fn ty_is_local(ty: Ty<'_>) -> bool {
match ty.kind() {
ty::Adt(adt_def, ..) => adt_def.did().is_local(),
// Arrays and slices use the inner type's `ConstParamTy`.
ty::Array(ty, ..) => ty_is_local(*ty),
ty::Slice(ty) => ty_is_local(*ty),
// `&` references use the inner type's `ConstParamTy`.
// `&mut` are not supported.
ty::Ref(_, ty, ast::Mutability::Not) => ty_is_local(*ty),
// Say that a tuple is local if any of its components are local.
// This is not strictly correct, but it's likely that the user can fix the local component.
ty::Tuple(tys) => tys.iter().any(|ty| ty_is_local(ty)),
_ => false,
}
}

let mut diag = match ty.kind() {
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Error(_) => return Ok(()),
ty::FnPtr(_) => tcx.dcx().struct_span_err(
Expand All @@ -962,35 +978,16 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
tcx,
tcx.param_env(param.def_id),
ty,
cause,
&cause,
) {
// Can never implement `ConstParamTy`, don't suggest anything.
Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => false,
Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed(..)) => false,
// May be able to implement `ConstParamTy`. Only emit the feature help
// if the type is local, since the user may be able to fix the local type.
Err(ConstParamTyImplementationError::InfrigingFields(..)) => {
fn ty_is_local(ty: Ty<'_>) -> bool {
match ty.kind() {
ty::Adt(adt_def, ..) => adt_def.did().is_local(),
// Arrays and slices use the inner type's `ConstParamTy`.
ty::Array(ty, ..) => ty_is_local(*ty),
ty::Slice(ty) => ty_is_local(*ty),
// `&` references use the inner type's `ConstParamTy`.
// `&mut` are not supported.
ty::Ref(_, ty, ast::Mutability::Not) => ty_is_local(*ty),
// Say that a tuple is local if any of its components are local.
// This is not strictly correct, but it's likely that the user can fix the local component.
ty::Tuple(tys) => tys.iter().any(|ty| ty_is_local(ty)),
_ => false,
}
}

ty_is_local(ty)
}
// Same as above.
Err(ConstParamTyImplementationError::InfringingInnerTy(def_id)) => {
def_id.is_local()
}
Err(
ConstParamTyImplementationError::InfrigingFields(..)
| ConstParamTyImplementationError::InfringingInnerTy(..),
) => ty_is_local(ty),
// Implments `ConstParamTy`, suggest adding the feature to enable.
Ok(..) => true,
};
Expand Down
29 changes: 19 additions & 10 deletions compiler/rustc_hir_analysis/src/coherence/builtin.rs
Expand Up @@ -127,22 +127,31 @@ fn visit_implementation_of_const_param_ty(
};

let cause = traits::ObligationCause::misc(span, impl_did);
match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, cause) {
match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, &cause) {
Ok(()) => Ok(()),
Err(ConstParamTyImplementationError::InfrigingFields(fields)) => {
Err(infringing_fields_error(tcx, fields, LangItem::ConstParamTy, impl_did, span))
}
Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => {
Err(tcx.dcx().emit_err(errors::ConstParamTyImplOnNonAdt { span }))
Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed(ty)) => {
Err(tcx.dcx().emit_err(errors::ConstParamTyImplOnNonAdt { span, ty }))
}
Err(ConstParamTyImplementationError::InfringingInnerTy(def_id)) => {
let def_span = tcx.def_span(def_id);
tcx.dcx().emit_err(errors::ConstParamTyImplOnInfringingInnerTy {
Err(ConstParamTyImplementationError::InfringingInnerTy(def_ids)) => {
let mut def_spans = vec![];
let mut suggs = vec![];
for def_id in def_ids {
let def_span = tcx.def_span(def_id);
def_spans.push(def_span);
if def_id.is_local() {
suggs.push(errors::ConstParamTyImplOnInfringingInnerTySugg {
span: def_span.shrink_to_lo(),
});
}
}
Err(tcx.dcx().emit_err(errors::ConstParamTyImplOnInfringingInnerTy {
span,
def_span,
def_descr: tcx.def_descr(def_id),
sugg: def_id.is_local().then_some(def_span.shrink_to_lo()),
});
def_spans,
suggs,
}))
}
}
}
Expand Down
26 changes: 17 additions & 9 deletions compiler/rustc_hir_analysis/src/errors.rs
Expand Up @@ -221,10 +221,11 @@ pub struct CopyImplOnNonAdt {

#[derive(Diagnostic)]
#[diag(hir_analysis_const_param_ty_impl_on_non_adt)]
pub struct ConstParamTyImplOnNonAdt {
pub struct ConstParamTyImplOnNonAdt<'tcx> {
#[primary_span]
#[label]
pub span: Span,
pub ty: Ty<'tcx>,
}

#[derive(Diagnostic)]
Expand All @@ -233,14 +234,21 @@ pub struct ConstParamTyImplOnInfringingInnerTy {
#[primary_span]
pub span: Span,
#[label]
pub def_span: Span,
pub def_descr: &'static str,
#[suggestion(
applicability = "maybe-incorrect",
style = "verbose",
code = "#[derive(ConstParamTy)]\n"
)]
pub sugg: Option<Span>,
pub def_spans: Vec<Span>,
#[subdiagnostic]
pub suggs: Vec<ConstParamTyImplOnInfringingInnerTySugg>,
}

#[derive(Subdiagnostic)]
#[suggestion(
hir_analysis_const_param_ty_impl_on_infringing_inner_ty_sugg,
applicability = "maybe-incorrect",
style = "verbose",
code = "#[derive(ConstParamTy)]\n"
)]
pub struct ConstParamTyImplOnInfringingInnerTySugg {
#[primary_span]
pub span: Span,
}

#[derive(Diagnostic)]
Expand Down

0 comments on commit 486c90d

Please sign in to comment.