Skip to content

Commit 5bd8c96

Browse files
committed
provide generic_param_scope for region errors
1 parent b955fa7 commit 5bd8c96

22 files changed

+179
-175
lines changed

compiler/rustc_borrowck/src/diagnostics/region_errors.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -181,11 +181,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
181181
let generic_ty = type_test.generic_kind.to_ty(self.infcx.tcx);
182182
let origin = RelateParamBound(type_test_span, generic_ty, None);
183183
self.buffer_error(self.infcx.construct_generic_bound_failure(
184+
self.body.source.def_id().expect_local(),
184185
type_test_span,
185186
Some(origin),
186187
type_test.generic_kind,
187188
lower_bound_region,
188-
self.body.source.def_id().as_local(),
189189
));
190190
} else {
191191
// FIXME. We should handle this case better. It

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+28-56
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, Mul
6363
use rustc_hir as hir;
6464
use rustc_hir::def_id::{DefId, LocalDefId};
6565
use rustc_hir::lang_items::LangItem;
66-
use rustc_hir::{Item, ItemKind, Node};
66+
use rustc_hir::Node;
6767
use rustc_middle::dep_graph::DepContext;
6868
use rustc_middle::ty::print::with_no_trimmed_paths;
6969
use rustc_middle::ty::{
@@ -348,7 +348,11 @@ pub fn same_type_modulo_infer<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
348348
}
349349

350350
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
351-
pub fn report_region_errors(&self, errors: &[RegionResolutionError<'tcx>]) {
351+
pub fn report_region_errors(
352+
&self,
353+
generic_param_scope: LocalDefId,
354+
errors: &[RegionResolutionError<'tcx>],
355+
) {
352356
debug!("report_region_errors(): {} errors to start", errors.len());
353357

354358
// try to pre-process the errors, which will group some of them
@@ -379,6 +383,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
379383

380384
RegionResolutionError::GenericBoundFailure(origin, param_ty, sub) => {
381385
self.report_generic_bound_failure(
386+
generic_param_scope,
382387
origin.span(),
383388
Some(origin),
384389
param_ty,
@@ -2269,56 +2274,30 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
22692274

22702275
pub fn report_generic_bound_failure(
22712276
&self,
2277+
generic_param_scope: LocalDefId,
22722278
span: Span,
22732279
origin: Option<SubregionOrigin<'tcx>>,
22742280
bound_kind: GenericKind<'tcx>,
22752281
sub: Region<'tcx>,
22762282
) {
2277-
let owner =
2278-
self.in_progress_typeck_results.map(|typeck_results| typeck_results.borrow().hir_owner);
2279-
self.construct_generic_bound_failure(span, origin, bound_kind, sub, owner).emit();
2283+
self.construct_generic_bound_failure(generic_param_scope, span, origin, bound_kind, sub)
2284+
.emit();
22802285
}
22812286

22822287
pub fn construct_generic_bound_failure(
22832288
&self,
2289+
generic_param_scope: LocalDefId,
22842290
span: Span,
22852291
origin: Option<SubregionOrigin<'tcx>>,
22862292
bound_kind: GenericKind<'tcx>,
22872293
sub: Region<'tcx>,
2288-
owner: Option<LocalDefId>,
22892294
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
2290-
let hir = self.tcx.hir();
22912295
// Attempt to obtain the span of the parameter so we can
22922296
// suggest adding an explicit lifetime bound to it.
2293-
let generics = owner.map(|owner| {
2294-
let hir_id = hir.local_def_id_to_hir_id(owner);
2295-
let parent_id = hir.get_parent_item(hir_id);
2296-
(
2297-
// Parent item could be a `mod`, so we check the HIR before calling:
2298-
if let Some(Node::Item(Item {
2299-
kind: ItemKind::Trait(..) | ItemKind::Impl { .. },
2300-
..
2301-
})) = hir.find_by_def_id(parent_id)
2302-
{
2303-
Some(self.tcx.generics_of(parent_id))
2304-
} else {
2305-
None
2306-
},
2307-
self.tcx.generics_of(owner.to_def_id()),
2308-
hir.span(hir_id),
2309-
)
2310-
});
2311-
2312-
let span = match generics {
2313-
// This is to get around the trait identity obligation, that has a `DUMMY_SP` as signal
2314-
// for other diagnostics, so we need to recover it here.
2315-
Some((_, _, node)) if span.is_dummy() => node,
2316-
_ => span,
2317-
};
2318-
2297+
let generics = self.tcx.generics_of(generic_param_scope);
23192298
// type_param_span is (span, has_bounds)
2320-
let type_param_span = match (generics, bound_kind) {
2321-
(Some((_, ref generics, _)), GenericKind::Param(ref param)) => {
2299+
let type_param_span = match bound_kind {
2300+
GenericKind::Param(ref param) => {
23222301
// Account for the case where `param` corresponds to `Self`,
23232302
// which doesn't have the expected type argument.
23242303
if !(generics.has_self && param.index == 0) {
@@ -2346,30 +2325,23 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
23462325
}
23472326
_ => None,
23482327
};
2349-
let new_lt = generics
2350-
.as_ref()
2351-
.and_then(|(parent_g, g, _)| {
2352-
let mut possible = (b'a'..=b'z').map(|c| format!("'{}", c as char));
2353-
let mut lts_names = g
2354-
.params
2355-
.iter()
2328+
2329+
let new_lt = {
2330+
let mut possible = (b'a'..=b'z').map(|c| format!("'{}", c as char));
2331+
let lts_names =
2332+
iter::successors(Some(generics), |g| g.parent.map(|p| self.tcx.generics_of(p)))
2333+
.flat_map(|g| &g.params)
23562334
.filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
23572335
.map(|p| p.name.as_str())
23582336
.collect::<Vec<_>>();
2359-
if let Some(g) = parent_g {
2360-
lts_names.extend(
2361-
g.params
2362-
.iter()
2363-
.filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
2364-
.map(|p| p.name.as_str()),
2365-
);
2366-
}
2367-
possible.find(|candidate| !lts_names.contains(&&candidate[..]))
2368-
})
2369-
.unwrap_or("'lt".to_string());
2337+
possible
2338+
.find(|candidate| !lts_names.contains(&&candidate[..]))
2339+
.unwrap_or("'lt".to_string())
2340+
};
2341+
23702342
let add_lt_sugg = generics
2371-
.as_ref()
2372-
.and_then(|(_, g, _)| g.params.first())
2343+
.params
2344+
.first()
23732345
.and_then(|param| param.def_id.as_local())
23742346
.map(|def_id| (self.tcx.def_span(def_id).shrink_to_lo(), format!("{}, ", new_lt)));
23752347

@@ -2571,7 +2543,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
25712543
);
25722544
if let Some(infer::RelateParamBound(_, t, _)) = origin {
25732545
let return_impl_trait =
2574-
owner.and_then(|owner| self.tcx.return_type_impl_trait(owner)).is_some();
2546+
self.tcx.return_type_impl_trait(generic_param_scope).is_some();
25752547
let t = self.resolve_vars_if_possible(t);
25762548
match t.kind() {
25772549
// We've got:

compiler/rustc_infer/src/infer/mod.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -1301,7 +1301,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
13011301
/// result. After this, no more unification operations should be
13021302
/// done -- or the compiler will panic -- but it is legal to use
13031303
/// `resolve_vars_if_possible` as well as `fully_resolve`.
1304-
pub fn resolve_regions_and_report_errors(&self, outlives_env: &OutlivesEnvironment<'tcx>) {
1304+
pub fn resolve_regions_and_report_errors(
1305+
&self,
1306+
generic_param_scope: LocalDefId,
1307+
outlives_env: &OutlivesEnvironment<'tcx>,
1308+
) {
13051309
let errors = self.resolve_regions(outlives_env);
13061310

13071311
if !self.is_tainted_by_errors() {
@@ -1310,7 +1314,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
13101314
// this infcx was in use. This is totally hokey but
13111315
// otherwise we have a hard time separating legit region
13121316
// errors from silly ones.
1313-
self.report_region_errors(&errors);
1317+
self.report_region_errors(generic_param_scope, &errors);
13141318
}
13151319
}
13161320

compiler/rustc_infer/src/infer/outlives/obligations.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ use crate::infer::{
6868
};
6969
use crate::traits::{ObligationCause, ObligationCauseCode};
7070
use rustc_data_structures::undo_log::UndoLogs;
71+
use rustc_hir::def_id::LocalDefId;
7172
use rustc_middle::ty::subst::GenericArgKind;
7273
use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeVisitable};
7374
use smallvec::smallvec;
@@ -163,14 +164,15 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
163164

164165
pub fn check_region_obligations_and_report_errors(
165166
&self,
167+
generic_param_scope: LocalDefId,
166168
outlives_env: &OutlivesEnvironment<'tcx>,
167169
) {
168170
self.process_registered_region_obligations(
169171
outlives_env.region_bound_pairs(),
170172
outlives_env.param_env,
171173
);
172174

173-
self.resolve_regions_and_report_errors(outlives_env)
175+
self.resolve_regions_and_report_errors(generic_param_scope, outlives_env)
174176
}
175177
}
176178

compiler/rustc_trait_selection/src/traits/mod.rs

+23-15
Original file line numberDiff line numberDiff line change
@@ -237,29 +237,37 @@ fn do_normalize_predicates<'tcx>(
237237
// cares about declarations like `'a: 'b`.
238238
let outlives_env = OutlivesEnvironment::new(elaborated_env);
239239

240-
infcx.resolve_regions_and_report_errors(&outlives_env);
240+
// FIXME: It's very weird that we ignore region obligations but apparently
241+
// still need to use `resolve_regions` as we need the resolved regions in
242+
// the normalized predicates.
243+
let errors = infcx.resolve_regions(&outlives_env);
244+
if !errors.is_empty() {
245+
tcx.sess.delay_span_bug(
246+
span,
247+
format!(
248+
"failed region resolution while normalizing {elaborated_env:?}: {errors:?}"
249+
),
250+
);
251+
}
241252

242-
let predicates = match infcx.fully_resolve(predicates) {
243-
Ok(predicates) => predicates,
253+
match infcx.fully_resolve(predicates) {
254+
Ok(predicates) => Ok(predicates),
244255
Err(fixup_err) => {
245256
// If we encounter a fixup error, it means that some type
246257
// variable wound up unconstrained. I actually don't know
247258
// if this can happen, and I certainly don't expect it to
248259
// happen often, but if it did happen it probably
249260
// represents a legitimate failure due to some kind of
250-
// unconstrained variable, and it seems better not to ICE,
251-
// all things considered.
252-
let reported = tcx.sess.span_err(span, &fixup_err.to_string());
253-
return Err(reported);
261+
// unconstrained variable.
262+
//
263+
// @lcnr: Let's still ICE here for now. I want a test case
264+
// for that.
265+
span_bug!(
266+
span,
267+
"inference variables in normalized parameter environment: {}",
268+
fixup_err
269+
);
254270
}
255-
};
256-
if predicates.needs_infer() {
257-
let reported = tcx
258-
.sess
259-
.delay_span_bug(span, "encountered inference variables after `fully_resolve`");
260-
Err(reported)
261-
} else {
262-
Ok(predicates)
263271
}
264272
})
265273
}

compiler/rustc_typeck/src/check/check.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,10 @@ fn check_opaque_meets_bounds<'tcx>(
767767
// Can have different predicates to their defining use
768768
hir::OpaqueTyOrigin::TyAlias => {
769769
let outlives_environment = OutlivesEnvironment::new(param_env);
770-
infcx.check_region_obligations_and_report_errors(&outlives_environment);
770+
infcx.check_region_obligations_and_report_errors(
771+
defining_use_anchor,
772+
&outlives_environment,
773+
);
771774
}
772775
}
773776

compiler/rustc_typeck/src/check/compare_method.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,10 @@ fn compare_predicate_entailment<'tcx>(
394394
// lifetime parameters.
395395
let mut outlives_environment = OutlivesEnvironment::new(param_env);
396396
outlives_environment.add_implied_bounds(infcx, wf_tys, impl_m_hir_id);
397-
infcx.check_region_obligations_and_report_errors(&outlives_environment);
397+
infcx.check_region_obligations_and_report_errors(
398+
impl_m.def_id.expect_local(),
399+
&outlives_environment,
400+
);
398401

399402
Ok(())
400403
})
@@ -1145,7 +1148,8 @@ pub(crate) fn compare_const_impl<'tcx>(
11451148
}
11461149

11471150
let outlives_environment = OutlivesEnvironment::new(param_env);
1148-
infcx.resolve_regions_and_report_errors(&outlives_environment);
1151+
infcx
1152+
.resolve_regions_and_report_errors(impl_c.def_id.expect_local(), &outlives_environment);
11491153
});
11501154
}
11511155

@@ -1262,7 +1266,10 @@ fn compare_type_predicate_entailment<'tcx>(
12621266
// Finally, resolve all regions. This catches wily misuses of
12631267
// lifetime parameters.
12641268
let outlives_environment = OutlivesEnvironment::new(param_env);
1265-
infcx.check_region_obligations_and_report_errors(&outlives_environment);
1269+
infcx.check_region_obligations_and_report_errors(
1270+
impl_ty.def_id.expect_local(),
1271+
&outlives_environment,
1272+
);
12661273

12671274
Ok(())
12681275
})
@@ -1493,7 +1500,10 @@ pub fn check_type_bounds<'tcx>(
14931500
};
14941501
let mut outlives_environment = OutlivesEnvironment::new(param_env);
14951502
outlives_environment.add_implied_bounds(&infcx, implied_bounds, impl_ty_hir_id);
1496-
infcx.check_region_obligations_and_report_errors(&outlives_environment);
1503+
infcx.check_region_obligations_and_report_errors(
1504+
impl_ty.def_id.expect_local(),
1505+
&outlives_environment,
1506+
);
14971507

14981508
Ok(())
14991509
})

compiler/rustc_typeck/src/check/wfcheck.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
107107

108108
let mut outlives_environment = OutlivesEnvironment::new(param_env);
109109
outlives_environment.add_implied_bounds(infcx, wf_tys, body_id);
110-
infcx.check_region_obligations_and_report_errors(&outlives_environment);
110+
infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment);
111111
})
112112
}
113113

compiler/rustc_typeck/src/coherence/builtin.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ fn visit_implementation_of_dispatch_from_dyn<'tcx>(tcx: TyCtxt<'tcx>, impl_did:
349349

350350
// Finally, resolve all regions.
351351
let outlives_env = OutlivesEnvironment::new(param_env);
352-
infcx.resolve_regions_and_report_errors(&outlives_env);
352+
infcx.resolve_regions_and_report_errors(impl_did, &outlives_env);
353353
}
354354
}
355355
_ => {
@@ -606,7 +606,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
606606

607607
// Finally, resolve all regions.
608608
let outlives_env = OutlivesEnvironment::new(param_env);
609-
infcx.resolve_regions_and_report_errors(&outlives_env);
609+
infcx.resolve_regions_and_report_errors(impl_did, &outlives_env);
610610

611611
CoerceUnsizedInfo { custom_kind: kind }
612612
})

compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ fn get_impl_substs<'tcx>(
150150

151151
// Conservatively use an empty `ParamEnv`.
152152
let outlives_env = OutlivesEnvironment::new(ty::ParamEnv::empty());
153-
infcx.resolve_regions_and_report_errors(&outlives_env);
153+
infcx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env);
154154
let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
155155
let span = tcx.def_span(impl1_def_id);
156156
tcx.sess.emit_err(SubstsOnOverriddenImpl { span });

src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr

+5-3
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@ error[E0310]: the parameter type `T` may not live long enough
22
--> $DIR/builtin-superkinds-self-type.rs:10:16
33
|
44
LL | impl <T: Sync> Foo for T { }
5-
| ^^^
5+
| ^^^ ...so that the type `T` will meet its required lifetime bounds...
66
|
7-
= help: consider adding an explicit lifetime bound `T: 'static`...
8-
= note: ...so that the type `T` will meet its required lifetime bounds...
97
note: ...that is required by this bound
108
--> $DIR/builtin-superkinds-self-type.rs:6:24
119
|
1210
LL | trait Foo : Sized+Sync+'static {
1311
| ^^^^^^^
12+
help: consider adding an explicit lifetime bound...
13+
|
14+
LL | impl <T: Sync + 'static> Foo for T { }
15+
| +++++++++
1416

1517
error: aborting due to previous error
1618

src/test/ui/fn/implied-bounds-unnorm-associated-type-3.stderr

+5-3
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ error[E0310]: the parameter type `T` may not live long enough
22
--> $DIR/implied-bounds-unnorm-associated-type-3.rs:19:5
33
|
44
LL | fn zero_copy_from<'b>(cart: &'b [T]) -> &'b [T] {
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `[T]` will meet its required lifetime bounds
66
|
7-
= help: consider adding an explicit lifetime bound `T: 'static`...
8-
= note: ...so that the type `[T]` will meet its required lifetime bounds
7+
help: consider adding an explicit lifetime bound...
8+
|
9+
LL | impl<T: 'static> ZeroCopyFrom<[T]> for &'static [T] {
10+
| +++++++++
911

1012
error: aborting due to previous error
1113

0 commit comments

Comments
 (0)