Add initial implementation of HIR-based WF checking for diagnostics
During well-formed checking, we walk through all types 'nested' in
generic arguments. For example, WF-checking `Option<MyStruct<u8>>`
will cause us to check `MyStruct<u8>` and `u8`. However, this is done
on a `rustc_middle::ty::Ty`, which has no span information. As a result,
any errors that occur will have a very general span (e.g. the
definintion of an associated item).
This becomes a problem when macros are involved. In general, an
associated type like `type MyType = Option<MyStruct<u8>>;` may
have completely different spans for each nested type in the HIR. Using
the span of the entire associated item might end up pointing to a macro
invocation, even though a user-provided span is available in one of the
nested types.
This PR adds a framework for HIR-based well formed checking. This check
is only run during error reporting, and is used to obtain a more precise
span for an existing error. This is accomplished by individually
checking each 'nested' type in the HIR for the type, allowing us to
find the most-specific type (and span) that produces a given error.
The majority of the changes are to the error-reporting code. However,
some of the general trait code is modified to pass through more
information.
Since this has no soundness implications, I've implemented a minimal
version to begin with, which can be extended over time. In particular,
this only works for HIR items with a corresponding `DefId` (e.g. it will
not work for WF-checking performed within function bodies).
2021-04-04 20:55:39 +00:00
|
|
|
use crate::collect::ItemCtxt;
|
|
|
|
use rustc_hir as hir;
|
2021-11-03 23:03:12 +00:00
|
|
|
use rustc_hir::intravisit::{self, Visitor};
|
2022-06-16 04:44:07 +00:00
|
|
|
use rustc_hir::{ForeignItem, ForeignItemKind, HirId};
|
Add initial implementation of HIR-based WF checking for diagnostics
During well-formed checking, we walk through all types 'nested' in
generic arguments. For example, WF-checking `Option<MyStruct<u8>>`
will cause us to check `MyStruct<u8>` and `u8`. However, this is done
on a `rustc_middle::ty::Ty`, which has no span information. As a result,
any errors that occur will have a very general span (e.g. the
definintion of an associated item).
This becomes a problem when macros are involved. In general, an
associated type like `type MyType = Option<MyStruct<u8>>;` may
have completely different spans for each nested type in the HIR. Using
the span of the entire associated item might end up pointing to a macro
invocation, even though a user-provided span is available in one of the
nested types.
This PR adds a framework for HIR-based well formed checking. This check
is only run during error reporting, and is used to obtain a more precise
span for an existing error. This is accomplished by individually
checking each 'nested' type in the HIR for the type, allowing us to
find the most-specific type (and span) that produces a given error.
The majority of the changes are to the error-reporting code. However,
some of the general trait code is modified to pass through more
information.
Since this has no soundness implications, I've implemented a minimal
version to begin with, which can be extended over time. In particular,
this only works for HIR items with a corresponding `DefId` (e.g. it will
not work for WF-checking performed within function bodies).
2021-04-04 20:55:39 +00:00
|
|
|
use rustc_infer::infer::TyCtxtInferExt;
|
Support HIR wf checking for function signatures
During function type-checking, we normalize any associated types in
the function signature (argument types + return type), and then
create WF obligations for each of the normalized types. The HIR wf code
does not currently support this case, so any errors that we get have
imprecise spans.
This commit extends `ObligationCauseCode::WellFormed` to support
recording a function parameter, allowing us to get the corresponding
HIR type if an error occurs. Function typechecking is modified to
pass this information during signature normalization and WF checking.
The resulting code is fairly verbose, due to the fact that we can
no longer normalize the entire signature with a single function call.
As part of the refactoring, we now perform HIR-based WF checking
for several other 'typed items' (statics, consts, and inherent impls).
As a result, WF and projection errors in a function signature now
have a precise span, which points directly at the responsible type.
If a function signature is constructed via a macro, this will allow
the error message to point at the code 'most responsible' for the error
(e.g. a user-supplied macro argument).
2021-07-18 16:33:49 +00:00
|
|
|
use rustc_infer::traits::{ObligationCause, WellFormedLoc};
|
Add initial implementation of HIR-based WF checking for diagnostics
During well-formed checking, we walk through all types 'nested' in
generic arguments. For example, WF-checking `Option<MyStruct<u8>>`
will cause us to check `MyStruct<u8>` and `u8`. However, this is done
on a `rustc_middle::ty::Ty`, which has no span information. As a result,
any errors that occur will have a very general span (e.g. the
definintion of an associated item).
This becomes a problem when macros are involved. In general, an
associated type like `type MyType = Option<MyStruct<u8>>;` may
have completely different spans for each nested type in the HIR. Using
the span of the entire associated item might end up pointing to a macro
invocation, even though a user-provided span is available in one of the
nested types.
This PR adds a framework for HIR-based well formed checking. This check
is only run during error reporting, and is used to obtain a more precise
span for an existing error. This is accomplished by individually
checking each 'nested' type in the HIR for the type, allowing us to
find the most-specific type (and span) that produces a given error.
The majority of the changes are to the error-reporting code. However,
some of the general trait code is modified to pass through more
information.
Since this has no soundness implications, I've implemented a minimal
version to begin with, which can be extended over time. In particular,
this only works for HIR items with a corresponding `DefId` (e.g. it will
not work for WF-checking performed within function bodies).
2021-04-04 20:55:39 +00:00
|
|
|
use rustc_middle::ty::query::Providers;
|
Support HIR wf checking for function signatures
During function type-checking, we normalize any associated types in
the function signature (argument types + return type), and then
create WF obligations for each of the normalized types. The HIR wf code
does not currently support this case, so any errors that we get have
imprecise spans.
This commit extends `ObligationCauseCode::WellFormed` to support
recording a function parameter, allowing us to get the corresponding
HIR type if an error occurs. Function typechecking is modified to
pass this information during signature normalization and WF checking.
The resulting code is fairly verbose, due to the fact that we can
no longer normalize the entire signature with a single function call.
As part of the refactoring, we now perform HIR-based WF checking
for several other 'typed items' (statics, consts, and inherent impls).
As a result, WF and projection errors in a function signature now
have a precise span, which points directly at the responsible type.
If a function signature is constructed via a macro, this will allow
the error message to point at the code 'most responsible' for the error
(e.g. a user-supplied macro argument).
2021-07-18 16:33:49 +00:00
|
|
|
use rustc_middle::ty::{self, Region, ToPredicate, TyCtxt, TypeFoldable, TypeFolder};
|
2022-08-02 06:02:04 +00:00
|
|
|
use rustc_trait_selection::traits;
|
Add initial implementation of HIR-based WF checking for diagnostics
During well-formed checking, we walk through all types 'nested' in
generic arguments. For example, WF-checking `Option<MyStruct<u8>>`
will cause us to check `MyStruct<u8>` and `u8`. However, this is done
on a `rustc_middle::ty::Ty`, which has no span information. As a result,
any errors that occur will have a very general span (e.g. the
definintion of an associated item).
This becomes a problem when macros are involved. In general, an
associated type like `type MyType = Option<MyStruct<u8>>;` may
have completely different spans for each nested type in the HIR. Using
the span of the entire associated item might end up pointing to a macro
invocation, even though a user-provided span is available in one of the
nested types.
This PR adds a framework for HIR-based well formed checking. This check
is only run during error reporting, and is used to obtain a more precise
span for an existing error. This is accomplished by individually
checking each 'nested' type in the HIR for the type, allowing us to
find the most-specific type (and span) that produces a given error.
The majority of the changes are to the error-reporting code. However,
some of the general trait code is modified to pass through more
information.
Since this has no soundness implications, I've implemented a minimal
version to begin with, which can be extended over time. In particular,
this only works for HIR items with a corresponding `DefId` (e.g. it will
not work for WF-checking performed within function bodies).
2021-04-04 20:55:39 +00:00
|
|
|
|
|
|
|
pub fn provide(providers: &mut Providers) {
|
|
|
|
*providers = Providers { diagnostic_hir_wf_check, ..*providers };
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ideally, this would be in `rustc_trait_selection`, but we
|
|
|
|
// need access to `ItemCtxt`
|
|
|
|
fn diagnostic_hir_wf_check<'tcx>(
|
|
|
|
tcx: TyCtxt<'tcx>,
|
Support HIR wf checking for function signatures
During function type-checking, we normalize any associated types in
the function signature (argument types + return type), and then
create WF obligations for each of the normalized types. The HIR wf code
does not currently support this case, so any errors that we get have
imprecise spans.
This commit extends `ObligationCauseCode::WellFormed` to support
recording a function parameter, allowing us to get the corresponding
HIR type if an error occurs. Function typechecking is modified to
pass this information during signature normalization and WF checking.
The resulting code is fairly verbose, due to the fact that we can
no longer normalize the entire signature with a single function call.
As part of the refactoring, we now perform HIR-based WF checking
for several other 'typed items' (statics, consts, and inherent impls).
As a result, WF and projection errors in a function signature now
have a precise span, which points directly at the responsible type.
If a function signature is constructed via a macro, this will allow
the error message to point at the code 'most responsible' for the error
(e.g. a user-supplied macro argument).
2021-07-18 16:33:49 +00:00
|
|
|
(predicate, loc): (ty::Predicate<'tcx>, WellFormedLoc),
|
Add initial implementation of HIR-based WF checking for diagnostics
During well-formed checking, we walk through all types 'nested' in
generic arguments. For example, WF-checking `Option<MyStruct<u8>>`
will cause us to check `MyStruct<u8>` and `u8`. However, this is done
on a `rustc_middle::ty::Ty`, which has no span information. As a result,
any errors that occur will have a very general span (e.g. the
definintion of an associated item).
This becomes a problem when macros are involved. In general, an
associated type like `type MyType = Option<MyStruct<u8>>;` may
have completely different spans for each nested type in the HIR. Using
the span of the entire associated item might end up pointing to a macro
invocation, even though a user-provided span is available in one of the
nested types.
This PR adds a framework for HIR-based well formed checking. This check
is only run during error reporting, and is used to obtain a more precise
span for an existing error. This is accomplished by individually
checking each 'nested' type in the HIR for the type, allowing us to
find the most-specific type (and span) that produces a given error.
The majority of the changes are to the error-reporting code. However,
some of the general trait code is modified to pass through more
information.
Since this has no soundness implications, I've implemented a minimal
version to begin with, which can be extended over time. In particular,
this only works for HIR items with a corresponding `DefId` (e.g. it will
not work for WF-checking performed within function bodies).
2021-04-04 20:55:39 +00:00
|
|
|
) -> Option<ObligationCause<'tcx>> {
|
|
|
|
let hir = tcx.hir();
|
|
|
|
|
Support HIR wf checking for function signatures
During function type-checking, we normalize any associated types in
the function signature (argument types + return type), and then
create WF obligations for each of the normalized types. The HIR wf code
does not currently support this case, so any errors that we get have
imprecise spans.
This commit extends `ObligationCauseCode::WellFormed` to support
recording a function parameter, allowing us to get the corresponding
HIR type if an error occurs. Function typechecking is modified to
pass this information during signature normalization and WF checking.
The resulting code is fairly verbose, due to the fact that we can
no longer normalize the entire signature with a single function call.
As part of the refactoring, we now perform HIR-based WF checking
for several other 'typed items' (statics, consts, and inherent impls).
As a result, WF and projection errors in a function signature now
have a precise span, which points directly at the responsible type.
If a function signature is constructed via a macro, this will allow
the error message to point at the code 'most responsible' for the error
(e.g. a user-supplied macro argument).
2021-07-18 16:33:49 +00:00
|
|
|
let def_id = match loc {
|
|
|
|
WellFormedLoc::Ty(def_id) => def_id,
|
|
|
|
WellFormedLoc::Param { function, param_idx: _ } => function,
|
Add initial implementation of HIR-based WF checking for diagnostics
During well-formed checking, we walk through all types 'nested' in
generic arguments. For example, WF-checking `Option<MyStruct<u8>>`
will cause us to check `MyStruct<u8>` and `u8`. However, this is done
on a `rustc_middle::ty::Ty`, which has no span information. As a result,
any errors that occur will have a very general span (e.g. the
definintion of an associated item).
This becomes a problem when macros are involved. In general, an
associated type like `type MyType = Option<MyStruct<u8>>;` may
have completely different spans for each nested type in the HIR. Using
the span of the entire associated item might end up pointing to a macro
invocation, even though a user-provided span is available in one of the
nested types.
This PR adds a framework for HIR-based well formed checking. This check
is only run during error reporting, and is used to obtain a more precise
span for an existing error. This is accomplished by individually
checking each 'nested' type in the HIR for the type, allowing us to
find the most-specific type (and span) that produces a given error.
The majority of the changes are to the error-reporting code. However,
some of the general trait code is modified to pass through more
information.
Since this has no soundness implications, I've implemented a minimal
version to begin with, which can be extended over time. In particular,
this only works for HIR items with a corresponding `DefId` (e.g. it will
not work for WF-checking performed within function bodies).
2021-04-04 20:55:39 +00:00
|
|
|
};
|
2021-07-20 15:56:33 +00:00
|
|
|
let hir_id = hir.local_def_id_to_hir_id(def_id);
|
Support HIR wf checking for function signatures
During function type-checking, we normalize any associated types in
the function signature (argument types + return type), and then
create WF obligations for each of the normalized types. The HIR wf code
does not currently support this case, so any errors that we get have
imprecise spans.
This commit extends `ObligationCauseCode::WellFormed` to support
recording a function parameter, allowing us to get the corresponding
HIR type if an error occurs. Function typechecking is modified to
pass this information during signature normalization and WF checking.
The resulting code is fairly verbose, due to the fact that we can
no longer normalize the entire signature with a single function call.
As part of the refactoring, we now perform HIR-based WF checking
for several other 'typed items' (statics, consts, and inherent impls).
As a result, WF and projection errors in a function signature now
have a precise span, which points directly at the responsible type.
If a function signature is constructed via a macro, this will allow
the error message to point at the code 'most responsible' for the error
(e.g. a user-supplied macro argument).
2021-07-18 16:33:49 +00:00
|
|
|
|
|
|
|
// HIR wfcheck should only ever happen as part of improving an existing error
|
|
|
|
tcx.sess
|
|
|
|
.delay_span_bug(tcx.def_span(def_id), "Performed HIR wfcheck without an existing error!");
|
Add initial implementation of HIR-based WF checking for diagnostics
During well-formed checking, we walk through all types 'nested' in
generic arguments. For example, WF-checking `Option<MyStruct<u8>>`
will cause us to check `MyStruct<u8>` and `u8`. However, this is done
on a `rustc_middle::ty::Ty`, which has no span information. As a result,
any errors that occur will have a very general span (e.g. the
definintion of an associated item).
This becomes a problem when macros are involved. In general, an
associated type like `type MyType = Option<MyStruct<u8>>;` may
have completely different spans for each nested type in the HIR. Using
the span of the entire associated item might end up pointing to a macro
invocation, even though a user-provided span is available in one of the
nested types.
This PR adds a framework for HIR-based well formed checking. This check
is only run during error reporting, and is used to obtain a more precise
span for an existing error. This is accomplished by individually
checking each 'nested' type in the HIR for the type, allowing us to
find the most-specific type (and span) that produces a given error.
The majority of the changes are to the error-reporting code. However,
some of the general trait code is modified to pass through more
information.
Since this has no soundness implications, I've implemented a minimal
version to begin with, which can be extended over time. In particular,
this only works for HIR items with a corresponding `DefId` (e.g. it will
not work for WF-checking performed within function bodies).
2021-04-04 20:55:39 +00:00
|
|
|
|
|
|
|
let icx = ItemCtxt::new(tcx, def_id.to_def_id());
|
|
|
|
|
|
|
|
// To perform HIR-based WF checking, we iterate over all HIR types
|
|
|
|
// that occur 'inside' the item we're checking. For example,
|
|
|
|
// given the type `Option<MyStruct<u8>>`, we will check
|
|
|
|
// `Option<MyStruct<u8>>`, `MyStruct<u8>`, and `u8`.
|
|
|
|
// For each type, we perform a well-formed check, and see if we get
|
2021-07-27 20:24:43 +00:00
|
|
|
// an error that matches our expected predicate. We save
|
Add initial implementation of HIR-based WF checking for diagnostics
During well-formed checking, we walk through all types 'nested' in
generic arguments. For example, WF-checking `Option<MyStruct<u8>>`
will cause us to check `MyStruct<u8>` and `u8`. However, this is done
on a `rustc_middle::ty::Ty`, which has no span information. As a result,
any errors that occur will have a very general span (e.g. the
definintion of an associated item).
This becomes a problem when macros are involved. In general, an
associated type like `type MyType = Option<MyStruct<u8>>;` may
have completely different spans for each nested type in the HIR. Using
the span of the entire associated item might end up pointing to a macro
invocation, even though a user-provided span is available in one of the
nested types.
This PR adds a framework for HIR-based well formed checking. This check
is only run during error reporting, and is used to obtain a more precise
span for an existing error. This is accomplished by individually
checking each 'nested' type in the HIR for the type, allowing us to
find the most-specific type (and span) that produces a given error.
The majority of the changes are to the error-reporting code. However,
some of the general trait code is modified to pass through more
information.
Since this has no soundness implications, I've implemented a minimal
version to begin with, which can be extended over time. In particular,
this only works for HIR items with a corresponding `DefId` (e.g. it will
not work for WF-checking performed within function bodies).
2021-04-04 20:55:39 +00:00
|
|
|
// the `ObligationCause` corresponding to the *innermost* type,
|
|
|
|
// which is the most specific type that we can point to.
|
|
|
|
// In general, the different components of an `hir::Ty` may have
|
2021-07-27 20:24:43 +00:00
|
|
|
// completely different spans due to macro invocations. Pointing
|
Add initial implementation of HIR-based WF checking for diagnostics
During well-formed checking, we walk through all types 'nested' in
generic arguments. For example, WF-checking `Option<MyStruct<u8>>`
will cause us to check `MyStruct<u8>` and `u8`. However, this is done
on a `rustc_middle::ty::Ty`, which has no span information. As a result,
any errors that occur will have a very general span (e.g. the
definintion of an associated item).
This becomes a problem when macros are involved. In general, an
associated type like `type MyType = Option<MyStruct<u8>>;` may
have completely different spans for each nested type in the HIR. Using
the span of the entire associated item might end up pointing to a macro
invocation, even though a user-provided span is available in one of the
nested types.
This PR adds a framework for HIR-based well formed checking. This check
is only run during error reporting, and is used to obtain a more precise
span for an existing error. This is accomplished by individually
checking each 'nested' type in the HIR for the type, allowing us to
find the most-specific type (and span) that produces a given error.
The majority of the changes are to the error-reporting code. However,
some of the general trait code is modified to pass through more
information.
Since this has no soundness implications, I've implemented a minimal
version to begin with, which can be extended over time. In particular,
this only works for HIR items with a corresponding `DefId` (e.g. it will
not work for WF-checking performed within function bodies).
2021-04-04 20:55:39 +00:00
|
|
|
// to the most accurate part of the type can be the difference
|
|
|
|
// between a useless span (e.g. the macro invocation site)
|
2021-07-27 20:24:43 +00:00
|
|
|
// and a useful span (e.g. a user-provided type passed into the macro).
|
Add initial implementation of HIR-based WF checking for diagnostics
During well-formed checking, we walk through all types 'nested' in
generic arguments. For example, WF-checking `Option<MyStruct<u8>>`
will cause us to check `MyStruct<u8>` and `u8`. However, this is done
on a `rustc_middle::ty::Ty`, which has no span information. As a result,
any errors that occur will have a very general span (e.g. the
definintion of an associated item).
This becomes a problem when macros are involved. In general, an
associated type like `type MyType = Option<MyStruct<u8>>;` may
have completely different spans for each nested type in the HIR. Using
the span of the entire associated item might end up pointing to a macro
invocation, even though a user-provided span is available in one of the
nested types.
This PR adds a framework for HIR-based well formed checking. This check
is only run during error reporting, and is used to obtain a more precise
span for an existing error. This is accomplished by individually
checking each 'nested' type in the HIR for the type, allowing us to
find the most-specific type (and span) that produces a given error.
The majority of the changes are to the error-reporting code. However,
some of the general trait code is modified to pass through more
information.
Since this has no soundness implications, I've implemented a minimal
version to begin with, which can be extended over time. In particular,
this only works for HIR items with a corresponding `DefId` (e.g. it will
not work for WF-checking performed within function bodies).
2021-04-04 20:55:39 +00:00
|
|
|
//
|
|
|
|
// This approach is quite inefficient - we redo a lot of work done
|
|
|
|
// by the normal WF checker. However, this code is run at most once
|
|
|
|
// per reported error - it will have no impact when compilation succeeds,
|
2021-07-27 20:24:43 +00:00
|
|
|
// and should only have an impact if a very large number of errors is
|
|
|
|
// displayed to the user.
|
Add initial implementation of HIR-based WF checking for diagnostics
During well-formed checking, we walk through all types 'nested' in
generic arguments. For example, WF-checking `Option<MyStruct<u8>>`
will cause us to check `MyStruct<u8>` and `u8`. However, this is done
on a `rustc_middle::ty::Ty`, which has no span information. As a result,
any errors that occur will have a very general span (e.g. the
definintion of an associated item).
This becomes a problem when macros are involved. In general, an
associated type like `type MyType = Option<MyStruct<u8>>;` may
have completely different spans for each nested type in the HIR. Using
the span of the entire associated item might end up pointing to a macro
invocation, even though a user-provided span is available in one of the
nested types.
This PR adds a framework for HIR-based well formed checking. This check
is only run during error reporting, and is used to obtain a more precise
span for an existing error. This is accomplished by individually
checking each 'nested' type in the HIR for the type, allowing us to
find the most-specific type (and span) that produces a given error.
The majority of the changes are to the error-reporting code. However,
some of the general trait code is modified to pass through more
information.
Since this has no soundness implications, I've implemented a minimal
version to begin with, which can be extended over time. In particular,
this only works for HIR items with a corresponding `DefId` (e.g. it will
not work for WF-checking performed within function bodies).
2021-04-04 20:55:39 +00:00
|
|
|
struct HirWfCheck<'tcx> {
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
predicate: ty::Predicate<'tcx>,
|
|
|
|
cause: Option<ObligationCause<'tcx>>,
|
|
|
|
cause_depth: usize,
|
|
|
|
icx: ItemCtxt<'tcx>,
|
|
|
|
hir_id: HirId,
|
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
|
|
|
depth: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> {
|
|
|
|
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
|
2022-09-20 03:03:59 +00:00
|
|
|
let infcx = self.tcx.infer_ctxt().build();
|
|
|
|
let tcx_ty = self.icx.to_ty(ty).fold_with(&mut EraseAllBoundRegions { tcx: self.tcx });
|
|
|
|
let cause = traits::ObligationCause::new(
|
|
|
|
ty.span,
|
|
|
|
self.hir_id,
|
|
|
|
traits::ObligationCauseCode::WellFormed(None),
|
|
|
|
);
|
|
|
|
let errors = traits::fully_solve_obligation(
|
|
|
|
&infcx,
|
|
|
|
traits::Obligation::new(
|
|
|
|
cause,
|
|
|
|
self.param_env,
|
|
|
|
ty::Binder::dummy(ty::PredicateKind::WellFormed(tcx_ty.into()))
|
|
|
|
.to_predicate(self.tcx),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
if !errors.is_empty() {
|
|
|
|
debug!("Wf-check got errors for {:?}: {:?}", ty, errors);
|
|
|
|
for error in errors {
|
|
|
|
if error.obligation.predicate == self.predicate {
|
|
|
|
// Save the cause from the greatest depth - this corresponds
|
|
|
|
// to picking more-specific types (e.g. `MyStruct<u8>`)
|
|
|
|
// over less-specific types (e.g. `Option<MyStruct<u8>>`)
|
|
|
|
if self.depth >= self.cause_depth {
|
|
|
|
self.cause = Some(error.obligation.cause);
|
|
|
|
self.cause_depth = self.depth
|
Add initial implementation of HIR-based WF checking for diagnostics
During well-formed checking, we walk through all types 'nested' in
generic arguments. For example, WF-checking `Option<MyStruct<u8>>`
will cause us to check `MyStruct<u8>` and `u8`. However, this is done
on a `rustc_middle::ty::Ty`, which has no span information. As a result,
any errors that occur will have a very general span (e.g. the
definintion of an associated item).
This becomes a problem when macros are involved. In general, an
associated type like `type MyType = Option<MyStruct<u8>>;` may
have completely different spans for each nested type in the HIR. Using
the span of the entire associated item might end up pointing to a macro
invocation, even though a user-provided span is available in one of the
nested types.
This PR adds a framework for HIR-based well formed checking. This check
is only run during error reporting, and is used to obtain a more precise
span for an existing error. This is accomplished by individually
checking each 'nested' type in the HIR for the type, allowing us to
find the most-specific type (and span) that produces a given error.
The majority of the changes are to the error-reporting code. However,
some of the general trait code is modified to pass through more
information.
Since this has no soundness implications, I've implemented a minimal
version to begin with, which can be extended over time. In particular,
this only works for HIR items with a corresponding `DefId` (e.g. it will
not work for WF-checking performed within function bodies).
2021-04-04 20:55:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-09-20 03:03:59 +00:00
|
|
|
}
|
Add initial implementation of HIR-based WF checking for diagnostics
During well-formed checking, we walk through all types 'nested' in
generic arguments. For example, WF-checking `Option<MyStruct<u8>>`
will cause us to check `MyStruct<u8>` and `u8`. However, this is done
on a `rustc_middle::ty::Ty`, which has no span information. As a result,
any errors that occur will have a very general span (e.g. the
definintion of an associated item).
This becomes a problem when macros are involved. In general, an
associated type like `type MyType = Option<MyStruct<u8>>;` may
have completely different spans for each nested type in the HIR. Using
the span of the entire associated item might end up pointing to a macro
invocation, even though a user-provided span is available in one of the
nested types.
This PR adds a framework for HIR-based well formed checking. This check
is only run during error reporting, and is used to obtain a more precise
span for an existing error. This is accomplished by individually
checking each 'nested' type in the HIR for the type, allowing us to
find the most-specific type (and span) that produces a given error.
The majority of the changes are to the error-reporting code. However,
some of the general trait code is modified to pass through more
information.
Since this has no soundness implications, I've implemented a minimal
version to begin with, which can be extended over time. In particular,
this only works for HIR items with a corresponding `DefId` (e.g. it will
not work for WF-checking performed within function bodies).
2021-04-04 20:55:39 +00:00
|
|
|
self.depth += 1;
|
|
|
|
intravisit::walk_ty(self, ty);
|
|
|
|
self.depth -= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut visitor = HirWfCheck {
|
|
|
|
tcx,
|
|
|
|
predicate,
|
|
|
|
cause: None,
|
|
|
|
cause_depth: 0,
|
|
|
|
icx,
|
|
|
|
hir_id,
|
|
|
|
param_env: tcx.param_env(def_id.to_def_id()),
|
|
|
|
depth: 0,
|
|
|
|
};
|
|
|
|
|
Support HIR wf checking for function signatures
During function type-checking, we normalize any associated types in
the function signature (argument types + return type), and then
create WF obligations for each of the normalized types. The HIR wf code
does not currently support this case, so any errors that we get have
imprecise spans.
This commit extends `ObligationCauseCode::WellFormed` to support
recording a function parameter, allowing us to get the corresponding
HIR type if an error occurs. Function typechecking is modified to
pass this information during signature normalization and WF checking.
The resulting code is fairly verbose, due to the fact that we can
no longer normalize the entire signature with a single function call.
As part of the refactoring, we now perform HIR-based WF checking
for several other 'typed items' (statics, consts, and inherent impls).
As a result, WF and projection errors in a function signature now
have a precise span, which points directly at the responsible type.
If a function signature is constructed via a macro, this will allow
the error message to point at the code 'most responsible' for the error
(e.g. a user-supplied macro argument).
2021-07-18 16:33:49 +00:00
|
|
|
// Get the starting `hir::Ty` using our `WellFormedLoc`.
|
|
|
|
// We will walk 'into' this type to try to find
|
|
|
|
// a more precise span for our predicate.
|
|
|
|
let ty = match loc {
|
|
|
|
WellFormedLoc::Ty(_) => match hir.get(hir_id) {
|
|
|
|
hir::Node::ImplItem(item) => match item.kind {
|
2022-10-09 07:09:57 +00:00
|
|
|
hir::ImplItemKind::Type(ty) => Some(ty),
|
2021-07-27 20:24:43 +00:00
|
|
|
hir::ImplItemKind::Const(ty, _) => Some(ty),
|
Support HIR wf checking for function signatures
During function type-checking, we normalize any associated types in
the function signature (argument types + return type), and then
create WF obligations for each of the normalized types. The HIR wf code
does not currently support this case, so any errors that we get have
imprecise spans.
This commit extends `ObligationCauseCode::WellFormed` to support
recording a function parameter, allowing us to get the corresponding
HIR type if an error occurs. Function typechecking is modified to
pass this information during signature normalization and WF checking.
The resulting code is fairly verbose, due to the fact that we can
no longer normalize the entire signature with a single function call.
As part of the refactoring, we now perform HIR-based WF checking
for several other 'typed items' (statics, consts, and inherent impls).
As a result, WF and projection errors in a function signature now
have a precise span, which points directly at the responsible type.
If a function signature is constructed via a macro, this will allow
the error message to point at the code 'most responsible' for the error
(e.g. a user-supplied macro argument).
2021-07-18 16:33:49 +00:00
|
|
|
ref item => bug!("Unexpected ImplItem {:?}", item),
|
|
|
|
},
|
|
|
|
hir::Node::TraitItem(item) => match item.kind {
|
|
|
|
hir::TraitItemKind::Type(_, ty) => ty,
|
2021-07-27 20:24:43 +00:00
|
|
|
hir::TraitItemKind::Const(ty, _) => Some(ty),
|
Support HIR wf checking for function signatures
During function type-checking, we normalize any associated types in
the function signature (argument types + return type), and then
create WF obligations for each of the normalized types. The HIR wf code
does not currently support this case, so any errors that we get have
imprecise spans.
This commit extends `ObligationCauseCode::WellFormed` to support
recording a function parameter, allowing us to get the corresponding
HIR type if an error occurs. Function typechecking is modified to
pass this information during signature normalization and WF checking.
The resulting code is fairly verbose, due to the fact that we can
no longer normalize the entire signature with a single function call.
As part of the refactoring, we now perform HIR-based WF checking
for several other 'typed items' (statics, consts, and inherent impls).
As a result, WF and projection errors in a function signature now
have a precise span, which points directly at the responsible type.
If a function signature is constructed via a macro, this will allow
the error message to point at the code 'most responsible' for the error
(e.g. a user-supplied macro argument).
2021-07-18 16:33:49 +00:00
|
|
|
ref item => bug!("Unexpected TraitItem {:?}", item),
|
|
|
|
},
|
|
|
|
hir::Node::Item(item) => match item.kind {
|
|
|
|
hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _) => Some(ty),
|
|
|
|
hir::ItemKind::Impl(ref impl_) => {
|
|
|
|
assert!(impl_.of_trait.is_none(), "Unexpected trait impl: {:?}", impl_);
|
|
|
|
Some(impl_.self_ty)
|
|
|
|
}
|
|
|
|
ref item => bug!("Unexpected item {:?}", item),
|
|
|
|
},
|
2021-07-20 15:56:33 +00:00
|
|
|
hir::Node::Field(field) => Some(field.ty),
|
2022-06-16 04:44:07 +00:00
|
|
|
hir::Node::ForeignItem(ForeignItem {
|
|
|
|
kind: ForeignItemKind::Static(ty, _), ..
|
|
|
|
}) => Some(*ty),
|
2022-08-30 06:19:48 +00:00
|
|
|
hir::Node::GenericParam(hir::GenericParam {
|
|
|
|
kind: hir::GenericParamKind::Type { default: Some(ty), .. },
|
|
|
|
..
|
|
|
|
}) => Some(*ty),
|
Support HIR wf checking for function signatures
During function type-checking, we normalize any associated types in
the function signature (argument types + return type), and then
create WF obligations for each of the normalized types. The HIR wf code
does not currently support this case, so any errors that we get have
imprecise spans.
This commit extends `ObligationCauseCode::WellFormed` to support
recording a function parameter, allowing us to get the corresponding
HIR type if an error occurs. Function typechecking is modified to
pass this information during signature normalization and WF checking.
The resulting code is fairly verbose, due to the fact that we can
no longer normalize the entire signature with a single function call.
As part of the refactoring, we now perform HIR-based WF checking
for several other 'typed items' (statics, consts, and inherent impls).
As a result, WF and projection errors in a function signature now
have a precise span, which points directly at the responsible type.
If a function signature is constructed via a macro, this will allow
the error message to point at the code 'most responsible' for the error
(e.g. a user-supplied macro argument).
2021-07-18 16:33:49 +00:00
|
|
|
ref node => bug!("Unexpected node {:?}", node),
|
Add initial implementation of HIR-based WF checking for diagnostics
During well-formed checking, we walk through all types 'nested' in
generic arguments. For example, WF-checking `Option<MyStruct<u8>>`
will cause us to check `MyStruct<u8>` and `u8`. However, this is done
on a `rustc_middle::ty::Ty`, which has no span information. As a result,
any errors that occur will have a very general span (e.g. the
definintion of an associated item).
This becomes a problem when macros are involved. In general, an
associated type like `type MyType = Option<MyStruct<u8>>;` may
have completely different spans for each nested type in the HIR. Using
the span of the entire associated item might end up pointing to a macro
invocation, even though a user-provided span is available in one of the
nested types.
This PR adds a framework for HIR-based well formed checking. This check
is only run during error reporting, and is used to obtain a more precise
span for an existing error. This is accomplished by individually
checking each 'nested' type in the HIR for the type, allowing us to
find the most-specific type (and span) that produces a given error.
The majority of the changes are to the error-reporting code. However,
some of the general trait code is modified to pass through more
information.
Since this has no soundness implications, I've implemented a minimal
version to begin with, which can be extended over time. In particular,
this only works for HIR items with a corresponding `DefId` (e.g. it will
not work for WF-checking performed within function bodies).
2021-04-04 20:55:39 +00:00
|
|
|
},
|
Support HIR wf checking for function signatures
During function type-checking, we normalize any associated types in
the function signature (argument types + return type), and then
create WF obligations for each of the normalized types. The HIR wf code
does not currently support this case, so any errors that we get have
imprecise spans.
This commit extends `ObligationCauseCode::WellFormed` to support
recording a function parameter, allowing us to get the corresponding
HIR type if an error occurs. Function typechecking is modified to
pass this information during signature normalization and WF checking.
The resulting code is fairly verbose, due to the fact that we can
no longer normalize the entire signature with a single function call.
As part of the refactoring, we now perform HIR-based WF checking
for several other 'typed items' (statics, consts, and inherent impls).
As a result, WF and projection errors in a function signature now
have a precise span, which points directly at the responsible type.
If a function signature is constructed via a macro, this will allow
the error message to point at the code 'most responsible' for the error
(e.g. a user-supplied macro argument).
2021-07-18 16:33:49 +00:00
|
|
|
WellFormedLoc::Param { function: _, param_idx } => {
|
|
|
|
let fn_decl = hir.fn_decl_by_hir_id(hir_id).unwrap();
|
|
|
|
// Get return type
|
|
|
|
if param_idx as usize == fn_decl.inputs.len() {
|
|
|
|
match fn_decl.output {
|
|
|
|
hir::FnRetTy::Return(ty) => Some(ty),
|
|
|
|
// The unit type `()` is always well-formed
|
|
|
|
hir::FnRetTy::DefaultReturn(_span) => None,
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Some(&fn_decl.inputs[param_idx as usize])
|
|
|
|
}
|
|
|
|
}
|
Add initial implementation of HIR-based WF checking for diagnostics
During well-formed checking, we walk through all types 'nested' in
generic arguments. For example, WF-checking `Option<MyStruct<u8>>`
will cause us to check `MyStruct<u8>` and `u8`. However, this is done
on a `rustc_middle::ty::Ty`, which has no span information. As a result,
any errors that occur will have a very general span (e.g. the
definintion of an associated item).
This becomes a problem when macros are involved. In general, an
associated type like `type MyType = Option<MyStruct<u8>>;` may
have completely different spans for each nested type in the HIR. Using
the span of the entire associated item might end up pointing to a macro
invocation, even though a user-provided span is available in one of the
nested types.
This PR adds a framework for HIR-based well formed checking. This check
is only run during error reporting, and is used to obtain a more precise
span for an existing error. This is accomplished by individually
checking each 'nested' type in the HIR for the type, allowing us to
find the most-specific type (and span) that produces a given error.
The majority of the changes are to the error-reporting code. However,
some of the general trait code is modified to pass through more
information.
Since this has no soundness implications, I've implemented a minimal
version to begin with, which can be extended over time. In particular,
this only works for HIR items with a corresponding `DefId` (e.g. it will
not work for WF-checking performed within function bodies).
2021-04-04 20:55:39 +00:00
|
|
|
};
|
|
|
|
if let Some(ty) = ty {
|
|
|
|
visitor.visit_ty(ty);
|
|
|
|
}
|
|
|
|
visitor.cause
|
|
|
|
}
|
Support HIR wf checking for function signatures
During function type-checking, we normalize any associated types in
the function signature (argument types + return type), and then
create WF obligations for each of the normalized types. The HIR wf code
does not currently support this case, so any errors that we get have
imprecise spans.
This commit extends `ObligationCauseCode::WellFormed` to support
recording a function parameter, allowing us to get the corresponding
HIR type if an error occurs. Function typechecking is modified to
pass this information during signature normalization and WF checking.
The resulting code is fairly verbose, due to the fact that we can
no longer normalize the entire signature with a single function call.
As part of the refactoring, we now perform HIR-based WF checking
for several other 'typed items' (statics, consts, and inherent impls).
As a result, WF and projection errors in a function signature now
have a precise span, which points directly at the responsible type.
If a function signature is constructed via a macro, this will allow
the error message to point at the code 'most responsible' for the error
(e.g. a user-supplied macro argument).
2021-07-18 16:33:49 +00:00
|
|
|
|
|
|
|
struct EraseAllBoundRegions<'tcx> {
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
}
|
|
|
|
|
|
|
|
// Higher ranked regions are complicated.
|
|
|
|
// To make matters worse, the HIR WF check can instantiate them
|
|
|
|
// outside of a `Binder`, due to the way we (ab)use
|
|
|
|
// `ItemCtxt::to_ty`. To make things simpler, we just erase all
|
|
|
|
// of them, regardless of depth. At worse, this will give
|
|
|
|
// us an inaccurate span for an error message, but cannot
|
2022-03-30 19:14:15 +00:00
|
|
|
// lead to unsoundness (we call `delay_span_bug` at the start
|
Support HIR wf checking for function signatures
During function type-checking, we normalize any associated types in
the function signature (argument types + return type), and then
create WF obligations for each of the normalized types. The HIR wf code
does not currently support this case, so any errors that we get have
imprecise spans.
This commit extends `ObligationCauseCode::WellFormed` to support
recording a function parameter, allowing us to get the corresponding
HIR type if an error occurs. Function typechecking is modified to
pass this information during signature normalization and WF checking.
The resulting code is fairly verbose, due to the fact that we can
no longer normalize the entire signature with a single function call.
As part of the refactoring, we now perform HIR-based WF checking
for several other 'typed items' (statics, consts, and inherent impls).
As a result, WF and projection errors in a function signature now
have a precise span, which points directly at the responsible type.
If a function signature is constructed via a macro, this will allow
the error message to point at the code 'most responsible' for the error
(e.g. a user-supplied macro argument).
2021-07-18 16:33:49 +00:00
|
|
|
// of `diagnostic_hir_wf_check`).
|
|
|
|
impl<'tcx> TypeFolder<'tcx> for EraseAllBoundRegions<'tcx> {
|
|
|
|
fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
|
|
|
|
self.tcx
|
|
|
|
}
|
2021-12-01 00:55:57 +00:00
|
|
|
fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> {
|
2022-01-28 00:25:15 +00:00
|
|
|
if r.is_late_bound() { self.tcx.lifetimes.re_erased } else { r }
|
Support HIR wf checking for function signatures
During function type-checking, we normalize any associated types in
the function signature (argument types + return type), and then
create WF obligations for each of the normalized types. The HIR wf code
does not currently support this case, so any errors that we get have
imprecise spans.
This commit extends `ObligationCauseCode::WellFormed` to support
recording a function parameter, allowing us to get the corresponding
HIR type if an error occurs. Function typechecking is modified to
pass this information during signature normalization and WF checking.
The resulting code is fairly verbose, due to the fact that we can
no longer normalize the entire signature with a single function call.
As part of the refactoring, we now perform HIR-based WF checking
for several other 'typed items' (statics, consts, and inherent impls).
As a result, WF and projection errors in a function signature now
have a precise span, which points directly at the responsible type.
If a function signature is constructed via a macro, this will allow
the error message to point at the code 'most responsible' for the error
(e.g. a user-supplied macro argument).
2021-07-18 16:33:49 +00:00
|
|
|
}
|
|
|
|
}
|