Skip to content

Commit

Permalink
correct spans in parem_env to deduplicate errors
Browse files Browse the repository at this point in the history
  • Loading branch information
SparrowLii committed Sep 30, 2022
1 parent 33a9f16 commit f0ba469
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 10 deletions.
31 changes: 26 additions & 5 deletions compiler/rustc_trait_selection/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,12 +217,12 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
#[instrument(level = "debug", skip(tcx, elaborated_env))]
fn do_normalize_predicates<'tcx>(
tcx: TyCtxt<'tcx>,
cause: ObligationCause<'tcx>,
span: Span,
mut causes: impl Iterator<Item = ObligationCause<'tcx>> + Debug,
elaborated_env: ty::ParamEnv<'tcx>,
predicates: Vec<ty::Predicate<'tcx>>,
outlives: bool,
) -> Result<Vec<ty::Predicate<'tcx>>, ErrorGuaranteed> {
let span = cause.span;
// FIXME. We should really... do something with these region
// obligations. But this call just continues the older
// behavior (i.e., doesn't cause any new bugs), and it would
Expand All @@ -241,9 +241,10 @@ fn do_normalize_predicates<'tcx>(
if outlives
!= matches!(predicate.kind().skip_binder(), ty::PredicateKind::TypeOutlives(..))
{
causes.next().unwrap();
Ok(predicate)
} else {
fully_normalize(&infcx, cause.clone(), elaborated_env, predicate)
fully_normalize(&infcx, causes.next().unwrap(), elaborated_env, predicate)
}
}) {
Ok(predicates) => predicates,
Expand Down Expand Up @@ -304,6 +305,7 @@ fn do_normalize_predicates<'tcx>(

// FIXME: this is gonna need to be removed ...
/// Normalizes the parameter environment, reporting errors if they occur.
#[inline]
#[instrument(level = "debug", skip(tcx))]
pub fn normalize_param_env_or_error<'tcx>(
tcx: TyCtxt<'tcx>,
Expand Down Expand Up @@ -331,6 +333,23 @@ pub fn normalize_param_env_or_error<'tcx>(

debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates);

normalize_param_env_with_causes(
tcx,
unnormalized_env,
cause.span,
std::iter::repeat(cause),
predicates,
)
}

#[instrument(level = "debug", skip(tcx))]
pub fn normalize_param_env_with_causes<'tcx>(
tcx: TyCtxt<'tcx>,
unnormalized_env: ty::ParamEnv<'tcx>,
span: Span,
causes: impl Iterator<Item = ObligationCause<'tcx>> + Clone + Debug,
predicates: Vec<ty::Predicate<'tcx>>,
) -> ty::ParamEnv<'tcx> {
let elaborated_env = ty::ParamEnv::new(
tcx.intern_predicates(&predicates),
unnormalized_env.reveal(),
Expand Down Expand Up @@ -358,7 +377,8 @@ pub fn normalize_param_env_or_error<'tcx>(

let Ok(predicates) = do_normalize_predicates(
tcx,
cause.clone(),
span.clone(),
causes.clone(),
elaborated_env,
predicates,
false,
Expand All @@ -378,7 +398,8 @@ pub fn normalize_param_env_or_error<'tcx>(
);
let Ok(predicates) = do_normalize_predicates(
tcx,
cause,
span,
causes,
outlives_env,
predicates,
true
Expand Down
44 changes: 39 additions & 5 deletions compiler/rustc_ty_utils/src/ty.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_infer::traits::util::elaborate_obligations;
use rustc_infer::traits::Obligation;
use rustc_middle::ty::{self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt};
use rustc_trait_selection::traits;

Expand Down Expand Up @@ -110,7 +112,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
}
// Compute the bounds on Self and the type parameters.

let ty::InstantiatedPredicates { mut predicates, .. } =
let ty::InstantiatedPredicates { mut predicates, spans } =
tcx.predicates_of(def_id).instantiate_identity(tcx);

// Finally, we have to normalize the bounds in the environment, in
Expand All @@ -132,6 +134,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {

let local_did = def_id.as_local();
let hir_id = local_did.map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id));
let mut is_fn = false;

let constness = match hir_id {
Some(hir_id) => match tcx.hir().get(hir_id) {
Expand Down Expand Up @@ -181,8 +184,11 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
kind:
hir::ItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..),
..
})
| hir::Node::TraitItem(hir::TraitItem {
}) => {
is_fn = true;
*constness
}
hir::Node::TraitItem(hir::TraitItem {
kind:
hir::TraitItemKind::Fn(
hir::FnSig { header: hir::FnHeader { constness, .. }, .. },
Expand Down Expand Up @@ -214,8 +220,36 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
_ => hir::CRATE_HIR_ID,
};

let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
traits::normalize_param_env_or_error(tcx, unnormalized_env, cause)
let span = tcx.def_span(def_id);

if is_fn {
let mut spans = spans.into_iter();
let obligations: Vec<_> = predicates
.into_iter()
.map(|predicate| {
let cause = traits::ObligationCause::misc(spans.next().unwrap_or(span), body_id);
Obligation::new(cause, ty::ParamEnv::empty(), predicate)
})
.collect();

let (predicates, causes): (Vec<_>, Vec<_>) = elaborate_obligations(tcx, obligations)
.map(|obligation| (obligation.predicate, obligation.cause))
.unzip();

traits::normalize_param_env_with_causes(
tcx,
unnormalized_env,
span,
causes.into_iter(),
predicates,
)
} else {
traits::normalize_param_env_or_error(
tcx,
unnormalized_env,
traits::ObligationCause::misc(span, body_id),
)
}
}

/// Elaborate the environment.
Expand Down
17 changes: 17 additions & 0 deletions src/test/ui/associated-types/issue-102185.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// compile-flags: -Zdeduplicate-diagnostics=yes

fn f<T>(_: impl A<X = T>) {}
//~^ ERROR the trait bound `T: B` is not satisfied [E0277]
trait A: C<Z = <<Self as A>::X as B>::Y> {
type X: B;
}

trait B {
type Y;
}

trait C {
type Z;
}

fn main() {}
14 changes: 14 additions & 0 deletions src/test/ui/associated-types/issue-102185.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error[E0277]: the trait bound `T: B` is not satisfied
--> $DIR/issue-102185.rs:3:17
|
LL | fn f<T>(_: impl A<X = T>) {}
| ^^^^^^^^ the trait `B` is not implemented for `T`
|
help: consider restricting type parameter `T`
|
LL | fn f<T: B>(_: impl A<X = T>) {}
| +++

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.

0 comments on commit f0ba469

Please sign in to comment.