Skip to content

Commit 95c1838

Browse files
committed
Fix unresolved inference variable ICE.
This commit moves well-formedness check for the `UserTypeAnnotation::Ty(..)` case from always running to only when the code is reachable. This solves the ICE that resulted from `src/test/ui/issue-54943-1.rs` (a minimal repro of `dropck-eyepatch` run-pass tests that failed). The main well-formedness check that was intended to be run despite unreachable code still is, that being the `UserTypeAnnotation::TypeOf(..)` case. Before this PR, the other case wasn't being checked at all. It is possible to fix this ICE while still always checking well-formedness for the `UserTypeAnnotation::Ty(..)` case but that solution will ICE in unreachable code for that case, the diff for that change [can be found here](0). [0]: https://gist.github.com/davidtwco/f9751ffd9c0508f7251c0f17adc3af53
1 parent 6092d92 commit 95c1838

File tree

5 files changed

+79
-16
lines changed

5 files changed

+79
-16
lines changed

src/librustc_mir/borrow_check/nll/type_check/mod.rs

+44-14
Original file line numberDiff line numberDiff line change
@@ -933,19 +933,28 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
933933
for index in self.mir.user_type_annotations.indices() {
934934
let (span, _) = &self.mir.user_type_annotations[index];
935935
let type_annotation = self.instantiated_type_annotations[&index];
936-
if let Err(terr) = self.fully_perform_op(
937-
Locations::All(*span),
938-
ConstraintCategory::Assignment,
939-
self.param_env.and(type_op::ascribe_user_type::AscribeUserTypeWellFormed::new(
940-
type_annotation,
941-
)),
942-
) {
943-
span_mirbug!(
944-
self,
945-
type_annotation,
946-
"bad user type annotation: {:?}",
947-
terr,
948-
);
936+
match type_annotation {
937+
// We can't check the well-formedness of a `UserTypeAnnotation::Ty` here, it will
938+
// cause ICEs (see comment in `relate_type_and_user_type`).
939+
UserTypeAnnotation::TypeOf(..) => {
940+
if let Err(terr) = self.fully_perform_op(
941+
Locations::All(*span),
942+
ConstraintCategory::Assignment,
943+
self.param_env.and(
944+
type_op::ascribe_user_type::AscribeUserTypeWellFormed::new(
945+
type_annotation,
946+
)
947+
),
948+
) {
949+
span_mirbug!(
950+
self,
951+
type_annotation,
952+
"bad user type annotation: {:?}",
953+
terr,
954+
);
955+
}
956+
},
957+
_ => {},
949958
}
950959
}
951960
}
@@ -1079,7 +1088,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
10791088
a, v, user_ty, locations,
10801089
);
10811090

1082-
match self.instantiated_type_annotations[&user_ty.base] {
1091+
let type_annotation = self.instantiated_type_annotations[&user_ty.base];
1092+
match type_annotation {
10831093
UserTypeAnnotation::Ty(ty) => {
10841094
// The `TypeRelating` code assumes that "unresolved inference
10851095
// variables" appear in the "a" side, so flip `Contravariant`
@@ -1117,7 +1127,27 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
11171127
if let Ok(projected_ty) = curr_projected_ty {
11181128
let ty = projected_ty.to_ty(tcx);
11191129
self.relate_types(ty, v1, a, locations, category)?;
1130+
1131+
// We'll get an ICE if we check for well-formedness of a
1132+
// `UserTypeAnnotation::Ty` that hasn't had types related.
1133+
//
1134+
// Doing this without the types having been related will result in
1135+
// `probe_ty_var` failing in the canonicalizer - in practice, this
1136+
// results in three run-pass tests failing. You can work around that
1137+
// by keeping an vec of projections instead of annotations and performing
1138+
// the projections before storing into `instantiated_type_annotations`
1139+
// but that still fails in dead code.
1140+
self.fully_perform_op(
1141+
locations,
1142+
category,
1143+
self.param_env.and(
1144+
type_op::ascribe_user_type::AscribeUserTypeWellFormed::new(
1145+
UserTypeAnnotation::Ty(ty),
1146+
)
1147+
),
1148+
)?;
11201149
}
1150+
11211151
}
11221152
UserTypeAnnotation::TypeOf(def_id, user_substs) => {
11231153
let projs = self.infcx.tcx.intern_projs(&user_ty.projs);

src/test/incremental/hashes/let_expressions.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ pub fn change_mutability_of_reference_type() {
7070

7171
#[cfg(not(cfail1))]
7272
#[rustc_clean(cfg="cfail2",
73-
except="HirBody,TypeckTables,MirValidated")]
73+
except="HirBody,TypeckTables,MirValidated,MirOptimized")]
7474
#[rustc_clean(cfg="cfail3")]
7575
pub fn change_mutability_of_reference_type() {
7676
let _x: &mut u64;

src/test/ui/issue-54943-1.rs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#![feature(nll)]
2+
3+
// This test is a minimal version of an ICE in the dropck-eyepatch tests
4+
// found in the fix for #54943.
5+
6+
// compile-pass
7+
8+
fn foo<T>(_t: T) {
9+
}
10+
11+
fn main() {
12+
struct A<'a, B: 'a>(&'a B);
13+
let (a1, a2): (String, A<_>) = (String::from("auto"), A(&"this"));
14+
foo((a1, a2));
15+
}

src/test/ui/issue-54943-2.rs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#![feature(nll)]
2+
3+
// This test is a minimal version of an ICE in the dropck-eyepatch tests
4+
// found in the fix for #54943. In particular, this test is in unreachable
5+
// code as the initial fix for this ICE only worked if the code was reachable.
6+
7+
// compile-pass
8+
9+
fn foo<T>(_t: T) {
10+
}
11+
12+
fn main() {
13+
return;
14+
15+
struct A<'a, B: 'a>(&'a B);
16+
let (a1, a2): (String, A<_>) = (String::from("auto"), A(&"this"));
17+
foo((a1, a2));
18+
}

src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ LL | fn call1<'a>(x: &'a usize) {
2121
LL | let z: &'a & usize = &(&y);
2222
| ----------- ^^^^ borrowed value does not live long enough
2323
| |
24-
| assignment requires that `y` is borrowed for `'a`
24+
| type annotation requires that `y` is borrowed for `'a`
2525
...
2626
LL | }
2727
| - `y` dropped here while still borrowed

0 commit comments

Comments
 (0)