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).
This commit is contained in:
Aaron Hill
2021-04-04 16:55:39 -04:00
parent 59d92bd017
commit a765333738
23 changed files with 350 additions and 66 deletions

View File

@@ -1,6 +1,7 @@
use crate::infer::InferCtxt;
use crate::opaque_types::required_region_bounds;
use crate::traits;
use rustc_data_structures::sync::Lrc;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
@@ -9,7 +10,6 @@ use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstnes
use rustc_span::Span;
use std::iter;
use std::rc::Rc;
/// Returns the set of obligations needed to make `arg` well-formed.
/// If `arg` contains unresolved inference variables, this may include
/// further WF obligations. However, if `arg` IS an unresolved
@@ -295,7 +295,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_ref() {
let derived_cause = traits::DerivedObligationCause {
parent_trait_ref: parent_trait_ref.value,
parent_code: Rc::new(obligation.cause.code.clone()),
parent_code: Lrc::new(obligation.cause.code.clone()),
};
cause.make_mut().code =
traits::ObligationCauseCode::DerivedObligation(derived_cause);