From 7b6f5ed9562ad13b68224138992a06463de299c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 1 Mar 2020 10:46:07 -0800 Subject: [PATCH] `delay_span_bug` when codegen cannot select obligation Fix #69602, introduced in #60126 by letting the compiler continue past type checking after encountering errors. --- src/librustc/query/mod.rs | 2 +- src/librustc_infer/traits/codegen/mod.rs | 18 +++++++++------ src/librustc_mir/monomorphize/mod.rs | 2 +- src/librustc_ty/instance.rs | 2 +- ...issue-69602-type-err-during-codegen-ice.rs | 22 +++++++++++++++++++ ...e-69602-type-err-during-codegen-ice.stderr | 19 ++++++++++++++++ 6 files changed, 55 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs create mode 100644 src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index b3315cc3701da..27d9435ac57dd 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -650,7 +650,7 @@ rustc_queries! { Codegen { query codegen_fulfill_obligation( key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) - ) -> Vtable<'tcx, ()> { + ) -> Option> { no_force cache_on_disk_if { true } desc { |tcx| diff --git a/src/librustc_infer/traits/codegen/mod.rs b/src/librustc_infer/traits/codegen/mod.rs index bd4129a4de76c..f499565e9192a 100644 --- a/src/librustc_infer/traits/codegen/mod.rs +++ b/src/librustc_infer/traits/codegen/mod.rs @@ -19,7 +19,7 @@ use rustc::ty::{self, TyCtxt}; pub fn codegen_fulfill_obligation<'tcx>( ty: TyCtxt<'tcx>, (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>), -) -> Vtable<'tcx, ()> { +) -> Option> { // Remove any references to regions; this helps improve caching. let trait_ref = ty.erase_regions(&trait_ref); @@ -47,11 +47,15 @@ pub fn codegen_fulfill_obligation<'tcx>( // leading to an ambiguous result. So report this as an // overflow bug, since I believe this is the only case // where ambiguity can result. - bug!( - "Encountered ambiguity selecting `{:?}` during codegen, \ - presuming due to overflow", - trait_ref - ) + infcx.tcx.sess.delay_span_bug( + rustc_span::DUMMY_SP, + &format!( + "encountered ambiguity selecting `{:?}` during codegen, presuming due to \ + overflow or prior type error", + trait_ref + ), + ); + return None; } Err(e) => { bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref) @@ -71,7 +75,7 @@ pub fn codegen_fulfill_obligation<'tcx>( let vtable = infcx.drain_fulfillment_cx_or_panic(&mut fulfill_cx, &vtable); info!("Cache miss: {:?} => {:?}", trait_ref, vtable); - vtable + Some(vtable) }) } diff --git a/src/librustc_mir/monomorphize/mod.rs b/src/librustc_mir/monomorphize/mod.rs index 8bc63bfcfcbe3..3dff06967e50e 100644 --- a/src/librustc_mir/monomorphize/mod.rs +++ b/src/librustc_mir/monomorphize/mod.rs @@ -18,7 +18,7 @@ pub fn custom_coerce_unsize_info<'tcx>( }); match tcx.codegen_fulfill_obligation((ty::ParamEnv::reveal_all(), trait_ref)) { - traits::VtableImpl(traits::VtableImplData { impl_def_id, .. }) => { + Some(traits::VtableImpl(traits::VtableImplData { impl_def_id, .. })) => { tcx.coerce_unsized_info(impl_def_id).custom_kind.unwrap() } vtable => { diff --git a/src/librustc_ty/instance.rs b/src/librustc_ty/instance.rs index 484b774add462..c2b2196e74c61 100644 --- a/src/librustc_ty/instance.rs +++ b/src/librustc_ty/instance.rs @@ -70,7 +70,7 @@ fn resolve_associated_item<'tcx>( ); let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs); - let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref))); + let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref)))?; // Now that we know which impl is being used, we can dispatch to // the actual function: diff --git a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs new file mode 100644 index 0000000000000..2c5257ce063cb --- /dev/null +++ b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs @@ -0,0 +1,22 @@ +trait TraitA { + const VALUE: usize; +} + +struct A; +impl TraitA for A { + const VALUE: usize = 0; +} + +trait TraitB { + type MyA: TraitA; + const VALUE: usize = Self::MyA::VALUE; +} + +struct B; +impl TraitB for B { //~ ERROR not all trait items implemented, missing: `MyA` + type M = A; //~ ERROR type `M` is not a member of trait `TraitB` +} + +fn main() { + let _ = [0; B::VALUE]; +} diff --git a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr new file mode 100644 index 0000000000000..8ae0f8b804c93 --- /dev/null +++ b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr @@ -0,0 +1,19 @@ +error[E0437]: type `M` is not a member of trait `TraitB` + --> $DIR/issue-69602-type-err-during-codegen-ice.rs:17:5 + | +LL | type M = A; + | ^^^^^^^^^^^^^ not a member of trait `TraitB` + +error[E0046]: not all trait items implemented, missing: `MyA` + --> $DIR/issue-69602-type-err-during-codegen-ice.rs:16:1 + | +LL | type MyA: TraitA; + | ----------------- `MyA` from trait +... +LL | impl TraitB for B { + | ^^^^^^^^^^^^^^^^^ missing `MyA` in implementation + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0046, E0437. +For more information about an error, try `rustc --explain E0046`.