Skip to content

Commit f0ba469

Browse files
committed
correct spans in parem_env to deduplicate errors
1 parent 33a9f16 commit f0ba469

File tree

4 files changed

+96
-10
lines changed

4 files changed

+96
-10
lines changed

compiler/rustc_trait_selection/src/traits/mod.rs

+26-5
Original file line numberDiff line numberDiff line change
@@ -217,12 +217,12 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
217217
#[instrument(level = "debug", skip(tcx, elaborated_env))]
218218
fn do_normalize_predicates<'tcx>(
219219
tcx: TyCtxt<'tcx>,
220-
cause: ObligationCause<'tcx>,
220+
span: Span,
221+
mut causes: impl Iterator<Item = ObligationCause<'tcx>> + Debug,
221222
elaborated_env: ty::ParamEnv<'tcx>,
222223
predicates: Vec<ty::Predicate<'tcx>>,
223224
outlives: bool,
224225
) -> Result<Vec<ty::Predicate<'tcx>>, ErrorGuaranteed> {
225-
let span = cause.span;
226226
// FIXME. We should really... do something with these region
227227
// obligations. But this call just continues the older
228228
// behavior (i.e., doesn't cause any new bugs), and it would
@@ -241,9 +241,10 @@ fn do_normalize_predicates<'tcx>(
241241
if outlives
242242
!= matches!(predicate.kind().skip_binder(), ty::PredicateKind::TypeOutlives(..))
243243
{
244+
causes.next().unwrap();
244245
Ok(predicate)
245246
} else {
246-
fully_normalize(&infcx, cause.clone(), elaborated_env, predicate)
247+
fully_normalize(&infcx, causes.next().unwrap(), elaborated_env, predicate)
247248
}
248249
}) {
249250
Ok(predicates) => predicates,
@@ -304,6 +305,7 @@ fn do_normalize_predicates<'tcx>(
304305

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

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

336+
normalize_param_env_with_causes(
337+
tcx,
338+
unnormalized_env,
339+
cause.span,
340+
std::iter::repeat(cause),
341+
predicates,
342+
)
343+
}
344+
345+
#[instrument(level = "debug", skip(tcx))]
346+
pub fn normalize_param_env_with_causes<'tcx>(
347+
tcx: TyCtxt<'tcx>,
348+
unnormalized_env: ty::ParamEnv<'tcx>,
349+
span: Span,
350+
causes: impl Iterator<Item = ObligationCause<'tcx>> + Clone + Debug,
351+
predicates: Vec<ty::Predicate<'tcx>>,
352+
) -> ty::ParamEnv<'tcx> {
334353
let elaborated_env = ty::ParamEnv::new(
335354
tcx.intern_predicates(&predicates),
336355
unnormalized_env.reveal(),
@@ -358,7 +377,8 @@ pub fn normalize_param_env_or_error<'tcx>(
358377

359378
let Ok(predicates) = do_normalize_predicates(
360379
tcx,
361-
cause.clone(),
380+
span.clone(),
381+
causes.clone(),
362382
elaborated_env,
363383
predicates,
364384
false,
@@ -378,7 +398,8 @@ pub fn normalize_param_env_or_error<'tcx>(
378398
);
379399
let Ok(predicates) = do_normalize_predicates(
380400
tcx,
381-
cause,
401+
span,
402+
causes,
382403
outlives_env,
383404
predicates,
384405
true

compiler/rustc_ty_utils/src/ty.rs

+39-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use rustc_data_structures::fx::FxIndexSet;
22
use rustc_hir as hir;
33
use rustc_hir::def_id::DefId;
4+
use rustc_infer::traits::util::elaborate_obligations;
5+
use rustc_infer::traits::Obligation;
46
use rustc_middle::ty::{self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt};
57
use rustc_trait_selection::traits;
68

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

113-
let ty::InstantiatedPredicates { mut predicates, .. } =
115+
let ty::InstantiatedPredicates { mut predicates, spans } =
114116
tcx.predicates_of(def_id).instantiate_identity(tcx);
115117

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

133135
let local_did = def_id.as_local();
134136
let hir_id = local_did.map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id));
137+
let mut is_fn = false;
135138

136139
let constness = match hir_id {
137140
Some(hir_id) => match tcx.hir().get(hir_id) {
@@ -181,8 +184,11 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
181184
kind:
182185
hir::ItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..),
183186
..
184-
})
185-
| hir::Node::TraitItem(hir::TraitItem {
187+
}) => {
188+
is_fn = true;
189+
*constness
190+
}
191+
hir::Node::TraitItem(hir::TraitItem {
186192
kind:
187193
hir::TraitItemKind::Fn(
188194
hir::FnSig { header: hir::FnHeader { constness, .. }, .. },
@@ -214,8 +220,36 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
214220
_ => hir::CRATE_HIR_ID,
215221
};
216222

217-
let cause = traits::ObligationCause::misc(tcx.def_span(def_id), body_id);
218-
traits::normalize_param_env_or_error(tcx, unnormalized_env, cause)
223+
let span = tcx.def_span(def_id);
224+
225+
if is_fn {
226+
let mut spans = spans.into_iter();
227+
let obligations: Vec<_> = predicates
228+
.into_iter()
229+
.map(|predicate| {
230+
let cause = traits::ObligationCause::misc(spans.next().unwrap_or(span), body_id);
231+
Obligation::new(cause, ty::ParamEnv::empty(), predicate)
232+
})
233+
.collect();
234+
235+
let (predicates, causes): (Vec<_>, Vec<_>) = elaborate_obligations(tcx, obligations)
236+
.map(|obligation| (obligation.predicate, obligation.cause))
237+
.unzip();
238+
239+
traits::normalize_param_env_with_causes(
240+
tcx,
241+
unnormalized_env,
242+
span,
243+
causes.into_iter(),
244+
predicates,
245+
)
246+
} else {
247+
traits::normalize_param_env_or_error(
248+
tcx,
249+
unnormalized_env,
250+
traits::ObligationCause::misc(span, body_id),
251+
)
252+
}
219253
}
220254

221255
/// Elaborate the environment.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// compile-flags: -Zdeduplicate-diagnostics=yes
2+
3+
fn f<T>(_: impl A<X = T>) {}
4+
//~^ ERROR the trait bound `T: B` is not satisfied [E0277]
5+
trait A: C<Z = <<Self as A>::X as B>::Y> {
6+
type X: B;
7+
}
8+
9+
trait B {
10+
type Y;
11+
}
12+
13+
trait C {
14+
type Z;
15+
}
16+
17+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0277]: the trait bound `T: B` is not satisfied
2+
--> $DIR/issue-102185.rs:3:17
3+
|
4+
LL | fn f<T>(_: impl A<X = T>) {}
5+
| ^^^^^^^^ the trait `B` is not implemented for `T`
6+
|
7+
help: consider restricting type parameter `T`
8+
|
9+
LL | fn f<T: B>(_: impl A<X = T>) {}
10+
| +++
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)