Skip to content

Commit 4eee556

Browse files
committed
borrowck: defer opaque type errors
1 parent 8b95291 commit 4eee556

18 files changed

+193
-84
lines changed

compiler/rustc_borrowck/src/diagnostics/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ mod conflict_errors;
5151
mod explain_borrow;
5252
mod move_errors;
5353
mod mutability_errors;
54-
mod opaque_suggestions;
54+
mod opaque_types;
5555
mod region_errors;
5656

5757
pub(crate) use bound_region_errors::{ToUniverseInfo, UniverseInfo};

compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs renamed to compiler/rustc_borrowck/src/diagnostics/opaque_types.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,28 @@ use rustc_trait_selection::errors::impl_trait_overcapture_suggestion;
1818
use crate::MirBorrowckCtxt;
1919
use crate::borrow_set::BorrowData;
2020
use crate::consumers::RegionInferenceContext;
21+
use crate::region_infer::opaque_types::DeferredOpaqueTypeError;
2122
use crate::type_check::Locations;
2223

2324
impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
25+
pub(crate) fn report_opaque_type_errors(&mut self, errors: Vec<DeferredOpaqueTypeError<'tcx>>) {
26+
if errors.is_empty() {
27+
return;
28+
}
29+
let mut guar = None;
30+
for error in errors {
31+
guar = Some(match error {
32+
DeferredOpaqueTypeError::InvalidOpaqueTypeArgs(err) => err.report(self.infcx),
33+
DeferredOpaqueTypeError::LifetimeMismatchOpaqueParam(err) => {
34+
self.infcx.dcx().emit_err(err)
35+
}
36+
});
37+
}
38+
let guar = guar.unwrap();
39+
self.root_cx.set_tainted_by_errors(guar);
40+
self.infcx.set_tainted_by_errors(guar);
41+
}
42+
2443
/// Try to note when an opaque is involved in a borrowck error and that
2544
/// opaque captures lifetimes due to edition 2024.
2645
// FIXME: This code is otherwise somewhat general, and could easily be adapted

compiler/rustc_borrowck/src/diagnostics/region_errors.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,6 @@ impl<'tcx> RegionErrors<'tcx> {
9292
) -> impl Iterator<Item = (RegionErrorKind<'tcx>, ErrorGuaranteed)> {
9393
self.0.into_iter()
9494
}
95-
pub(crate) fn has_errors(&self) -> Option<ErrorGuaranteed> {
96-
self.0.get(0).map(|x| x.1)
97-
}
9895
}
9996

10097
impl std::fmt::Debug for RegionErrors<'_> {

compiler/rustc_borrowck/src/lib.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ fn do_mir_borrowck<'tcx>(
375375
polonius_context,
376376
);
377377

378-
regioncx.infer_opaque_types(root_cx, &infcx, opaque_type_values);
378+
let opaque_type_errors = regioncx.infer_opaque_types(root_cx, &infcx, opaque_type_values);
379379

380380
// Dump MIR results into a file, if that is enabled. This lets us
381381
// write unit-tests, as well as helping with debugging.
@@ -471,7 +471,11 @@ fn do_mir_borrowck<'tcx>(
471471
};
472472

473473
// Compute and report region errors, if any.
474-
mbcx.report_region_errors(nll_errors);
474+
if nll_errors.is_empty() {
475+
mbcx.report_opaque_type_errors(opaque_type_errors);
476+
} else {
477+
mbcx.report_region_errors(nll_errors);
478+
}
475479

476480
let (mut flow_analysis, flow_entry_states) =
477481
get_flow_results(tcx, body, &move_data, &borrow_set, &regioncx);

compiler/rustc_borrowck/src/nll.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,6 @@ pub(crate) fn compute_regions<'tcx>(
148148
let (closure_region_requirements, nll_errors) =
149149
regioncx.solve(infcx, body, polonius_output.clone());
150150

151-
if let Some(guar) = nll_errors.has_errors() {
152-
// Suppress unhelpful extra errors in `infer_opaque_types`.
153-
infcx.set_tainted_by_errors(guar);
154-
}
155-
156151
NllOutput {
157152
regioncx,
158153
polonius_input: polonius_facts.map(Box::new),

compiler/rustc_borrowck/src/region_infer/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ use crate::{
4444

4545
mod dump_mir;
4646
mod graphviz;
47-
mod opaque_types;
47+
pub(crate) mod opaque_types;
4848
mod reverse_sccs;
4949

5050
pub(crate) mod values;

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

Lines changed: 43 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,21 @@ use rustc_middle::ty::{
66
TypeVisitableExt, fold_regions,
77
};
88
use rustc_span::Span;
9-
use rustc_trait_selection::opaque_types::check_opaque_type_parameter_valid;
9+
use rustc_trait_selection::opaque_types::{
10+
InvalidOpaqueTypeArgs, check_opaque_type_parameter_valid,
11+
};
1012
use tracing::{debug, instrument};
1113

1214
use super::RegionInferenceContext;
1315
use crate::BorrowCheckRootCtxt;
1416
use crate::session_diagnostics::LifetimeMismatchOpaqueParam;
1517
use crate::universal_regions::RegionClassification;
1618

19+
pub(crate) enum DeferredOpaqueTypeError<'tcx> {
20+
InvalidOpaqueTypeArgs(InvalidOpaqueTypeArgs<'tcx>),
21+
LifetimeMismatchOpaqueParam(LifetimeMismatchOpaqueParam<'tcx>),
22+
}
23+
1724
impl<'tcx> RegionInferenceContext<'tcx> {
1825
/// Resolve any opaque types that were encountered while borrow checking
1926
/// this item. This is then used to get the type in the `type_of` query.
@@ -58,13 +65,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
5865
///
5966
/// [rustc-dev-guide chapter]:
6067
/// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html
61-
#[instrument(level = "debug", skip(self, root_cx, infcx), ret)]
68+
#[instrument(level = "debug", skip(self, root_cx, infcx))]
6269
pub(crate) fn infer_opaque_types(
6370
&self,
6471
root_cx: &mut BorrowCheckRootCtxt<'tcx>,
6572
infcx: &InferCtxt<'tcx>,
6673
opaque_ty_decls: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
67-
) {
74+
) -> Vec<DeferredOpaqueTypeError<'tcx>> {
75+
let mut errors = Vec::new();
6876
let mut decls_modulo_regions: FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueTypeKey<'tcx>, Span)> =
6977
FxIndexMap::default();
7078

@@ -124,8 +132,15 @@ impl<'tcx> RegionInferenceContext<'tcx> {
124132
});
125133
debug!(?concrete_type);
126134

127-
let ty =
128-
infcx.infer_opaque_definition_from_instantiation(opaque_type_key, concrete_type);
135+
let ty = match infcx
136+
.infer_opaque_definition_from_instantiation(opaque_type_key, concrete_type)
137+
{
138+
Ok(ty) => ty,
139+
Err(err) => {
140+
errors.push(DeferredOpaqueTypeError::InvalidOpaqueTypeArgs(err));
141+
continue;
142+
}
143+
};
129144

130145
// Sometimes, when the hidden type is an inference variable, it can happen that
131146
// the hidden type becomes the opaque type itself. In this case, this was an opaque
@@ -149,25 +164,27 @@ impl<'tcx> RegionInferenceContext<'tcx> {
149164
// non-region parameters. This is necessary because within the new solver we perform
150165
// various query operations modulo regions, and thus could unsoundly select some impls
151166
// that don't hold.
152-
if !ty.references_error()
153-
&& let Some((prev_decl_key, prev_span)) = decls_modulo_regions.insert(
154-
infcx.tcx.erase_regions(opaque_type_key),
155-
(opaque_type_key, concrete_type.span),
156-
)
157-
&& let Some((arg1, arg2)) = std::iter::zip(
158-
prev_decl_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
159-
opaque_type_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
160-
)
161-
.find(|(arg1, arg2)| arg1 != arg2)
167+
if let Some((prev_decl_key, prev_span)) = decls_modulo_regions.insert(
168+
infcx.tcx.erase_regions(opaque_type_key),
169+
(opaque_type_key, concrete_type.span),
170+
) && let Some((arg1, arg2)) = std::iter::zip(
171+
prev_decl_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
172+
opaque_type_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
173+
)
174+
.find(|(arg1, arg2)| arg1 != arg2)
162175
{
163-
infcx.dcx().emit_err(LifetimeMismatchOpaqueParam {
164-
arg: arg1,
165-
prev: arg2,
166-
span: prev_span,
167-
prev_span: concrete_type.span,
168-
});
176+
errors.push(DeferredOpaqueTypeError::LifetimeMismatchOpaqueParam(
177+
LifetimeMismatchOpaqueParam {
178+
arg: arg1,
179+
prev: arg2,
180+
span: prev_span,
181+
prev_span: concrete_type.span,
182+
},
183+
));
169184
}
170185
}
186+
187+
errors
171188
}
172189

173190
/// Map the regions in the type to named regions. This is similar to what
@@ -260,19 +277,13 @@ impl<'tcx> InferCtxt<'tcx> {
260277
&self,
261278
opaque_type_key: OpaqueTypeKey<'tcx>,
262279
instantiated_ty: OpaqueHiddenType<'tcx>,
263-
) -> Ty<'tcx> {
264-
if let Some(e) = self.tainted_by_errors() {
265-
return Ty::new_error(self.tcx, e);
266-
}
267-
268-
if let Err(err) = check_opaque_type_parameter_valid(
280+
) -> Result<Ty<'tcx>, InvalidOpaqueTypeArgs<'tcx>> {
281+
check_opaque_type_parameter_valid(
269282
self,
270283
opaque_type_key,
271284
instantiated_ty.span,
272285
DefiningScopeKind::MirBorrowck,
273-
) {
274-
return Ty::new_error(self.tcx, err.report(self));
275-
}
286+
)?;
276287

277288
let definition_ty = instantiated_ty
278289
.remap_generic_params_to_declaration_params(
@@ -282,10 +293,7 @@ impl<'tcx> InferCtxt<'tcx> {
282293
)
283294
.ty;
284295

285-
if let Err(e) = definition_ty.error_reported() {
286-
return Ty::new_error(self.tcx, e);
287-
}
288-
289-
definition_ty
296+
definition_ty.error_reported()?;
297+
Ok(definition_ty)
290298
}
291299
}

tests/crashes/135528.rs

Lines changed: 0 additions & 20 deletions
This file was deleted.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//@ compile-flags: -Zvalidate-mir -Zinline-mir=yes
2+
3+
// This previously introduced a `{type_error}`` in the MIR body
4+
// during the `PostAnalysisNormalize` pass. While the underlying issue
5+
// #135528 did not get fixed, this reproducer no longer ICEs.
6+
7+
#![feature(type_alias_impl_trait)]
8+
type Tait = impl Copy;
9+
10+
fn set(x: &isize) -> isize {
11+
*x
12+
}
13+
14+
#[define_opaque(Tait)]
15+
fn d(x: Tait) {
16+
set(x);
17+
}
18+
19+
#[define_opaque(Tait)]
20+
fn other_define() -> Tait {
21+
() //~^ ERROR concrete type differs from previous defining opaque type use
22+
}
23+
24+
fn main() {}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: concrete type differs from previous defining opaque type use
2+
--> $DIR/type-error-post-normalization-test.rs:20:22
3+
|
4+
LL | fn other_define() -> Tait {
5+
| ^^^^ expected `&isize`, got `()`
6+
|
7+
note: previous use here
8+
--> $DIR/type-error-post-normalization-test.rs:16:9
9+
|
10+
LL | set(x);
11+
| ^
12+
13+
error: aborting due to 1 previous error
14+

0 commit comments

Comments
 (0)