diff options
| author | David Wood <david@davidtw.co> | 2018-12-09 03:07:31 +0100 |
|---|---|---|
| committer | David Wood <david@davidtw.co> | 2018-12-30 14:30:59 +0100 |
| commit | 95c18382cb01480b99b55163c19f35907de80eb4 (patch) | |
| tree | b69ab6e7896afbe6a401be810530e3e4bc2c5965 /src | |
| parent | 6092d92d70c81861ed46f2496e62dc74183857fd (diff) | |
| download | rust-95c18382cb01480b99b55163c19f35907de80eb4.tar.gz rust-95c18382cb01480b99b55163c19f35907de80eb4.zip | |
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
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_mir/borrow_check/nll/type_check/mod.rs | 58 | ||||
| -rw-r--r-- | src/test/incremental/hashes/let_expressions.rs | 2 | ||||
| -rw-r--r-- | src/test/ui/issue-54943-1.rs | 15 | ||||
| -rw-r--r-- | src/test/ui/issue-54943-2.rs | 18 | ||||
| -rw-r--r-- | src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr | 2 |
5 files changed, 79 insertions, 16 deletions
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 2c49dbd969d..d0ca050f0df 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -933,19 +933,28 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { for index in self.mir.user_type_annotations.indices() { let (span, _) = &self.mir.user_type_annotations[index]; let type_annotation = self.instantiated_type_annotations[&index]; - if let Err(terr) = self.fully_perform_op( - Locations::All(*span), - ConstraintCategory::Assignment, - self.param_env.and(type_op::ascribe_user_type::AscribeUserTypeWellFormed::new( - type_annotation, - )), - ) { - span_mirbug!( - self, - type_annotation, - "bad user type annotation: {:?}", - terr, - ); + match type_annotation { + // We can't check the well-formedness of a `UserTypeAnnotation::Ty` here, it will + // cause ICEs (see comment in `relate_type_and_user_type`). + UserTypeAnnotation::TypeOf(..) => { + if let Err(terr) = self.fully_perform_op( + Locations::All(*span), + ConstraintCategory::Assignment, + self.param_env.and( + type_op::ascribe_user_type::AscribeUserTypeWellFormed::new( + type_annotation, + ) + ), + ) { + span_mirbug!( + self, + type_annotation, + "bad user type annotation: {:?}", + terr, + ); + } + }, + _ => {}, } } } @@ -1079,7 +1088,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { a, v, user_ty, locations, ); - match self.instantiated_type_annotations[&user_ty.base] { + let type_annotation = self.instantiated_type_annotations[&user_ty.base]; + match type_annotation { UserTypeAnnotation::Ty(ty) => { // The `TypeRelating` code assumes that "unresolved inference // variables" appear in the "a" side, so flip `Contravariant` @@ -1117,7 +1127,27 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { if let Ok(projected_ty) = curr_projected_ty { let ty = projected_ty.to_ty(tcx); self.relate_types(ty, v1, a, locations, category)?; + + // We'll get an ICE if we check for well-formedness of a + // `UserTypeAnnotation::Ty` that hasn't had types related. + // + // Doing this without the types having been related will result in + // `probe_ty_var` failing in the canonicalizer - in practice, this + // results in three run-pass tests failing. You can work around that + // by keeping an vec of projections instead of annotations and performing + // the projections before storing into `instantiated_type_annotations` + // but that still fails in dead code. + self.fully_perform_op( + locations, + category, + self.param_env.and( + type_op::ascribe_user_type::AscribeUserTypeWellFormed::new( + UserTypeAnnotation::Ty(ty), + ) + ), + )?; } + } UserTypeAnnotation::TypeOf(def_id, user_substs) => { let projs = self.infcx.tcx.intern_projs(&user_ty.projs); diff --git a/src/test/incremental/hashes/let_expressions.rs b/src/test/incremental/hashes/let_expressions.rs index 3aa66527ca7..b6050f059c2 100644 --- a/src/test/incremental/hashes/let_expressions.rs +++ b/src/test/incremental/hashes/let_expressions.rs @@ -70,7 +70,7 @@ pub fn change_mutability_of_reference_type() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,TypeckTables,MirValidated")] + except="HirBody,TypeckTables,MirValidated,MirOptimized")] #[rustc_clean(cfg="cfail3")] pub fn change_mutability_of_reference_type() { let _x: &mut u64; diff --git a/src/test/ui/issue-54943-1.rs b/src/test/ui/issue-54943-1.rs new file mode 100644 index 00000000000..7750e340361 --- /dev/null +++ b/src/test/ui/issue-54943-1.rs @@ -0,0 +1,15 @@ +#![feature(nll)] + +// This test is a minimal version of an ICE in the dropck-eyepatch tests +// found in the fix for #54943. + +// compile-pass + +fn foo<T>(_t: T) { +} + +fn main() { + struct A<'a, B: 'a>(&'a B); + let (a1, a2): (String, A<_>) = (String::from("auto"), A(&"this")); + foo((a1, a2)); +} diff --git a/src/test/ui/issue-54943-2.rs b/src/test/ui/issue-54943-2.rs new file mode 100644 index 00000000000..f829c38c35d --- /dev/null +++ b/src/test/ui/issue-54943-2.rs @@ -0,0 +1,18 @@ +#![feature(nll)] + +// This test is a minimal version of an ICE in the dropck-eyepatch tests +// found in the fix for #54943. In particular, this test is in unreachable +// code as the initial fix for this ICE only worked if the code was reachable. + +// compile-pass + +fn foo<T>(_t: T) { +} + +fn main() { + return; + + struct A<'a, B: 'a>(&'a B); + let (a1, a2): (String, A<_>) = (String::from("auto"), A(&"this")); + foo((a1, a2)); +} diff --git a/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr b/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr index abda7ec5e07..539343a6829 100644 --- a/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr +++ b/src/test/ui/regions/regions-free-region-ordering-caller1.nll.stderr @@ -21,7 +21,7 @@ LL | fn call1<'a>(x: &'a usize) { LL | let z: &'a & usize = &(&y); | ----------- ^^^^ borrowed value does not live long enough | | - | assignment requires that `y` is borrowed for `'a` + | type annotation requires that `y` is borrowed for `'a` ... LL | } | - `y` dropped here while still borrowed |
