Skip to content

Commit e674a8f

Browse files
committed
track spans for assumed_wf_types
1 parent 75726ca commit e674a8f

File tree

15 files changed

+70
-63
lines changed

15 files changed

+70
-63
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -4157,6 +4157,7 @@ dependencies = [
41574157
name = "rustc_ty_utils"
41584158
version = "0.0.0"
41594159
dependencies = [
4160+
"itertools",
41604161
"rustc_data_structures",
41614162
"rustc_errors",
41624163
"rustc_fluent_macro",

compiler/rustc_hir_analysis/src/check/check.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ fn check_opaque_meets_bounds<'tcx>(
461461
if tcx.def_kind(tcx.parent(def_id.to_def_id())) == DefKind::OpaqueTy => {}
462462
// Can have different predicates to their defining use
463463
hir::OpaqueTyOrigin::TyAlias { .. } => {
464-
let wf_tys = ocx.assumed_wf_types(param_env, span, def_id);
464+
let wf_tys = ocx.assumed_wf_types(param_env, def_id);
465465
let implied_bounds = infcx.implied_bounds_tys(param_env, def_id, wf_tys);
466466
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
467467
let _ = ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env);

compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2037,7 +2037,7 @@ pub(super) fn check_type_bounds<'tcx>(
20372037
_ => bug!(),
20382038
}
20392039
};
2040-
let assumed_wf_types = ocx.assumed_wf_types(param_env, impl_ty_span, impl_ty_def_id);
2040+
let assumed_wf_types = ocx.assumed_wf_types(param_env, impl_ty_def_id);
20412041

20422042
let normalize_cause = ObligationCause::new(
20432043
impl_ty_span,

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
105105
}
106106
f(&mut wfcx);
107107

108-
let assumed_wf_types = wfcx.ocx.assumed_wf_types(param_env, span, body_def_id);
108+
let assumed_wf_types = wfcx.ocx.assumed_wf_types(param_env, body_def_id);
109109
let implied_bounds = infcx.implied_bounds_tys(param_env, body_def_id, assumed_wf_types);
110110

111111
let errors = wfcx.select_all_or_error();

compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,7 @@ fn get_impl_substs(
176176
let ocx = ObligationCtxt::new(infcx);
177177
let param_env = tcx.param_env(impl1_def_id);
178178

179-
let assumed_wf_types =
180-
ocx.assumed_wf_types(param_env, tcx.def_span(impl1_def_id), impl1_def_id);
179+
let assumed_wf_types = ocx.assumed_wf_types(param_env, impl1_def_id);
181180

182181
let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id);
183182
let impl1_span = tcx.def_span(impl1_def_id);

compiler/rustc_middle/src/query/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -881,7 +881,7 @@ rustc_queries! {
881881
///
882882
/// Note that we've liberated the late bound regions of function signatures, so
883883
/// this can not be used to check whether these types are well formed.
884-
query assumed_wf_types(key: DefId) -> &'tcx ty::List<Ty<'tcx>> {
884+
query assumed_wf_types(key: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] {
885885
desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) }
886886
}
887887

compiler/rustc_trait_selection/src/traits/coherence.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ fn prove_negated_obligation<'tcx>(
427427
let body_def_id = body_def_id.as_local().unwrap_or(CRATE_DEF_ID);
428428

429429
let ocx = ObligationCtxt::new(&infcx);
430-
let wf_tys = ocx.assumed_wf_types(param_env, DUMMY_SP, body_def_id);
430+
let wf_tys = ocx.assumed_wf_types(param_env, body_def_id);
431431
let outlives_env = OutlivesEnvironment::with_bounds(
432432
param_env,
433433
infcx.implied_bounds_tys(param_env, body_def_id, wf_tys),

compiler/rustc_trait_selection/src/traits/engine.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ use rustc_middle::ty::ToPredicate;
2424
use rustc_middle::ty::TypeFoldable;
2525
use rustc_middle::ty::{self, Ty, TyCtxt};
2626
use rustc_session::config::TraitSolver;
27-
use rustc_span::Span;
2827

2928
pub trait TraitEngineExt<'tcx> {
3029
fn new(infcx: &InferCtxt<'tcx>) -> Box<Self>;
@@ -223,14 +222,11 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
223222
pub fn assumed_wf_types(
224223
&self,
225224
param_env: ty::ParamEnv<'tcx>,
226-
span: Span,
227225
def_id: LocalDefId,
228226
) -> FxIndexSet<Ty<'tcx>> {
229227
let tcx = self.infcx.tcx;
230-
let assumed_wf_types = tcx.assumed_wf_types(def_id);
231228
let mut implied_bounds = FxIndexSet::default();
232-
let cause = ObligationCause::misc(span, def_id);
233-
for ty in assumed_wf_types {
229+
for &(ty, span) in tcx.assumed_wf_types(def_id) {
234230
// FIXME(@lcnr): rustc currently does not check wf for types
235231
// pre-normalization, meaning that implied bounds are sometimes
236232
// incorrect. See #100910 for more details.
@@ -243,6 +239,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
243239
// sound and then uncomment this line again.
244240

245241
// implied_bounds.insert(ty);
242+
let cause = ObligationCause::misc(span, def_id);
246243
let normalized = self.normalize(&cause, param_env, ty);
247244
implied_bounds.insert(normalized);
248245
}

compiler/rustc_ty_utils/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ edition = "2021"
55

66
[dependencies]
77
tracing = "0.1"
8+
itertools = "0.10"
89
rustc_middle = { path = "../rustc_middle" }
910
rustc_data_structures = { path = "../rustc_data_structures" }
1011
rustc_errors = { path = "../rustc_errors" }

compiler/rustc_ty_utils/src/implied_bounds.rs

+56-20
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,56 @@
1-
use rustc_hir::{def::DefKind, def_id::DefId};
1+
use rustc_hir as hir;
2+
use rustc_hir::def::DefKind;
3+
use rustc_hir::def_id::LocalDefId;
24
use rustc_middle::query::Providers;
35
use rustc_middle::ty::{self, Ty, TyCtxt};
6+
use rustc_span::Span;
7+
use std::iter;
48

59
pub fn provide(providers: &mut Providers) {
610
*providers = Providers { assumed_wf_types, ..*providers };
711
}
812

9-
fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Ty<'_>> {
13+
fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] {
1014
match tcx.def_kind(def_id) {
1115
DefKind::Fn => {
1216
let sig = tcx.fn_sig(def_id).subst_identity();
13-
let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig);
14-
liberated_sig.inputs_and_output
17+
let liberated_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
18+
tcx.arena.alloc_from_iter(itertools::zip_eq(
19+
liberated_sig.inputs_and_output,
20+
fn_sig_spans(tcx, def_id),
21+
))
1522
}
1623
DefKind::AssocFn => {
1724
let sig = tcx.fn_sig(def_id).subst_identity();
18-
let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig);
25+
let liberated_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
1926
let mut assumed_wf_types: Vec<_> =
20-
tcx.assumed_wf_types(tcx.parent(def_id)).as_slice().into();
21-
assumed_wf_types.extend(liberated_sig.inputs_and_output);
22-
tcx.mk_type_list(&assumed_wf_types)
27+
tcx.assumed_wf_types(tcx.local_parent(def_id)).into();
28+
assumed_wf_types.extend(itertools::zip_eq(
29+
liberated_sig.inputs_and_output,
30+
fn_sig_spans(tcx, def_id),
31+
));
32+
tcx.arena.alloc_slice(&assumed_wf_types)
2333
}
2434
DefKind::Impl { .. } => {
25-
match tcx.impl_trait_ref(def_id) {
26-
Some(trait_ref) => {
27-
let types: Vec<_> = trait_ref.skip_binder().substs.types().collect();
28-
tcx.mk_type_list(&types)
29-
}
30-
// Only the impl self type
31-
None => tcx.mk_type_list(&[tcx.type_of(def_id).subst_identity()]),
32-
}
35+
// Trait arguments and the self type for trait impls or only the self type for
36+
// inherent impls.
37+
let tys = match tcx.impl_trait_ref(def_id) {
38+
Some(trait_ref) => trait_ref.skip_binder().substs.types().collect(),
39+
None => vec![tcx.type_of(def_id).subst_identity()],
40+
};
41+
42+
let mut impl_spans = impl_spans(tcx, def_id);
43+
tcx.arena.alloc_from_iter(tys.into_iter().map(|ty| (ty, impl_spans.next().unwrap())))
3344
}
34-
DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)),
35-
DefKind::OpaqueTy => match tcx.def_kind(tcx.parent(def_id)) {
45+
DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)),
46+
DefKind::OpaqueTy => match tcx.def_kind(tcx.local_parent(def_id)) {
3647
DefKind::TyAlias => ty::List::empty(),
37-
DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)),
48+
DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)),
3849
// Nested opaque types only occur in associated types:
3950
// ` type Opaque<T> = impl Trait<&'static T, AssocTy = impl Nested>; `
4051
// assumed_wf_types should include those of `Opaque<T>`, `Opaque<T>` itself
4152
// and `&'static T`.
42-
DefKind::OpaqueTy => bug!("unimplemented implied bounds for neseted opaque types"),
53+
DefKind::OpaqueTy => bug!("unimplemented implied bounds for nested opaque types"),
4354
def_kind @ _ => {
4455
bug!("unimplemented implied bounds for opaque types with parent {def_kind:?}")
4556
}
@@ -72,3 +83,28 @@ fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Ty<'_>> {
7283
| DefKind::Generator => ty::List::empty(),
7384
}
7485
}
86+
87+
fn fn_sig_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator<Item = Span> + '_ {
88+
let node = tcx.hir().get(tcx.local_def_id_to_hir_id(def_id));
89+
if let Some(decl) = node.fn_decl() {
90+
decl.inputs.iter().map(|ty| ty.span).chain(iter::once(decl.output.span()))
91+
} else {
92+
bug!("unexpected item for fn {def_id:?}: {node:?}")
93+
}
94+
}
95+
96+
fn impl_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator<Item = Span> + '_ {
97+
let item = tcx.hir().expect_item(def_id);
98+
if let hir::ItemKind::Impl(impl_) = item.kind {
99+
let trait_args = impl_
100+
.of_trait
101+
.into_iter()
102+
.flat_map(|trait_ref| trait_ref.path.segments.last().unwrap().args().args)
103+
.map(|arg| arg.span());
104+
let dummy_spans_for_default_args =
105+
impl_.of_trait.into_iter().flat_map(|trait_ref| iter::repeat(trait_ref.path.span));
106+
iter::once(impl_.self_ty.span).chain(trait_args).chain(dummy_spans_for_default_args)
107+
} else {
108+
bug!("unexpected item for impl {def_id:?}: {item:?}")
109+
}
110+
}

tests/ui/associated-inherent-types/issue-109789.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0308]: mismatched types
2-
--> $DIR/issue-109789.rs:18:1
2+
--> $DIR/issue-109789.rs:18:11
33
|
44
LL | fn bar(_: Foo<for<'a> fn(&'a ())>::Assoc) {}
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
66
|
77
= note: expected struct `Foo<fn(&'static ())>`
88
found struct `Foo<for<'a> fn(&'a ())>`

tests/ui/issues/issue-35570.rs

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ trait Trait2<'a> {
77

88
fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
99
//~^ ERROR the trait bound `for<'a> (): Trait2<'a>` is not satisfied
10-
//~| ERROR the trait bound `for<'a> (): Trait2<'a>` is not satisfied
1110
let _e: (usize, usize) = unsafe{mem::transmute(param)};
1211
}
1312

tests/ui/issues/issue-35570.stderr

+1-11
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,6 @@ error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied
44
LL | fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
55
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait2<'a>` is not implemented for `()`
66

7-
error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied
8-
--> $DIR/issue-35570.rs:8:1
9-
|
10-
LL | / fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
11-
LL | |
12-
LL | |
13-
LL | | let _e: (usize, usize) = unsafe{mem::transmute(param)};
14-
LL | | }
15-
| |_^ the trait `for<'a> Trait2<'a>` is not implemented for `()`
16-
17-
error: aborting due to 2 previous errors
7+
error: aborting due to previous error
188

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

tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs

-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ trait Trait2<'a, 'b> {
2020
// do not infer that.
2121
fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
2222
//~^ ERROR the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
23-
//~| ERROR the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
2423
{
2524
}
2625

tests/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr

+1-16
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,6 @@ help: consider restricting type parameter `T`
99
LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
1010
| ++++++++++++++++++++++++
1111

12-
error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
13-
--> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:1
14-
|
15-
LL | / fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
16-
LL | |
17-
LL | |
18-
LL | | {
19-
LL | | }
20-
| |_^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T`
21-
|
22-
help: consider restricting type parameter `T`
23-
|
24-
LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
25-
| ++++++++++++++++++++++++
26-
27-
error: aborting due to 2 previous errors
12+
error: aborting due to previous error
2813

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

0 commit comments

Comments
 (0)