diff options
| author | Camille GILLOT <gillot.camille@gmail.com> | 2022-05-01 11:03:14 +0200 | 
|---|---|---|
| committer | Camille GILLOT <gillot.camille@gmail.com> | 2022-05-11 08:28:02 +0200 | 
| commit | 6cfe52c094fcd9897d8c2b4ea713198a58000898 (patch) | |
| tree | 51610041eee4a5f5973a88d4b658f92326ae7441 /compiler/rustc_trait_selection/src/traits/codegen.rs | |
| parent | 532be942ddf8f40d086e54d157453434b16e9647 (diff) | |
| download | rust-6cfe52c094fcd9897d8c2b4ea713198a58000898.tar.gz rust-6cfe52c094fcd9897d8c2b4ea713198a58000898.zip  | |
Gracefully fail to resolve associated items instead of `delay_span_bug`.
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits/codegen.rs')
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/codegen.rs | 91 | 
1 files changed, 16 insertions, 75 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs index c76a6542ca1..6ca630b74cc 100644 --- a/compiler/rustc_trait_selection/src/traits/codegen.rs +++ b/compiler/rustc_trait_selection/src/traits/codegen.rs @@ -3,13 +3,12 @@ // seems likely that they should eventually be merged into more // general routines. -use crate::infer::{InferCtxt, TyCtxtInferExt}; +use crate::infer::TyCtxtInferExt; use crate::traits::{ FulfillmentContext, ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine, Unimplemented, }; -use rustc_errors::ErrorGuaranteed; -use rustc_middle::ty::fold::TypeFoldable; +use rustc_middle::traits::CodegenObligationError; use rustc_middle::ty::{self, TyCtxt}; /// Attempts to resolve an obligation to an `ImplSource`. The result is @@ -23,7 +22,7 @@ use rustc_middle::ty::{self, TyCtxt}; pub fn codegen_fulfill_obligation<'tcx>( tcx: TyCtxt<'tcx>, (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>), -) -> Result<&'tcx ImplSource<'tcx, ()>, ErrorGuaranteed> { +) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> { // Remove any references to regions; this helps improve caching. let trait_ref = tcx.erase_regions(trait_ref); // We expect the input to be fully normalized. @@ -40,37 +39,8 @@ pub fn codegen_fulfill_obligation<'tcx>( let selection = match selcx.select(&obligation) { Ok(Some(selection)) => selection, - Ok(None) => { - // Ambiguity can happen when monomorphizing during trans - // expands to some humongous type that never occurred - // statically -- this humongous type can then overflow, - // leading to an ambiguous result. So report this as an - // overflow bug, since I believe this is the only case - // where ambiguity can result. - let reported = 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 Err(reported); - } - Err(Unimplemented) => { - // This can trigger when we probe for the source of a `'static` lifetime requirement - // on a trait object: `impl Foo for dyn Trait {}` has an implicit `'static` bound. - // This can also trigger when we have a global bound that is not actually satisfied, - // but was included during typeck due to the trivial_bounds feature. - let guar = infcx.tcx.sess.delay_span_bug( - rustc_span::DUMMY_SP, - &format!( - "Encountered error `Unimplemented` selecting `{:?}` during codegen", - trait_ref - ), - ); - return Err(guar); - } + Ok(None) => return Err(CodegenObligationError::Ambiguity), + Err(Unimplemented) => return Err(CodegenObligationError::Unimplemented), Err(e) => { bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref) } @@ -85,7 +55,17 @@ pub fn codegen_fulfill_obligation<'tcx>( let impl_source = selection.map(|predicate| { fulfill_cx.register_predicate_obligation(&infcx, predicate); }); - let impl_source = drain_fulfillment_cx_or_panic(&infcx, &mut fulfill_cx, impl_source); + + // In principle, we only need to do this so long as `impl_source` + // contains unbound type parameters. It could be a slight + // optimization to stop iterating early. + let errors = fulfill_cx.select_all_or_error(&infcx); + if !errors.is_empty() { + return Err(CodegenObligationError::FulfillmentError); + } + + let impl_source = infcx.resolve_vars_if_possible(impl_source); + let impl_source = infcx.tcx.erase_regions(impl_source); // Opaque types may have gotten their hidden types constrained, but we can ignore them safely // as they will get constrained elsewhere, too. @@ -95,42 +75,3 @@ pub fn codegen_fulfill_obligation<'tcx>( Ok(&*tcx.arena.alloc(impl_source)) }) } - -// # Global Cache - -/// Finishes processes any obligations that remain in the -/// fulfillment context, and then returns the result with all type -/// variables removed and regions erased. Because this is intended -/// for use outside of type inference, if any errors occur, -/// it will panic. It is used during normalization and other cases -/// where processing the obligations in `fulfill_cx` may cause -/// type inference variables that appear in `result` to be -/// unified, and hence we need to process those obligations to get -/// the complete picture of the type. -fn drain_fulfillment_cx_or_panic<'tcx, T>( - infcx: &InferCtxt<'_, 'tcx>, - fulfill_cx: &mut FulfillmentContext<'tcx>, - result: T, -) -> T -where - T: TypeFoldable<'tcx>, -{ - debug!("drain_fulfillment_cx_or_panic()"); - - // In principle, we only need to do this so long as `result` - // contains unbound type parameters. It could be a slight - // optimization to stop iterating early. - let errors = fulfill_cx.select_all_or_error(infcx); - if !errors.is_empty() { - infcx.tcx.sess.delay_span_bug( - rustc_span::DUMMY_SP, - &format!( - "Encountered errors `{:?}` resolving bounds outside of type inference", - errors - ), - ); - } - - let result = infcx.resolve_vars_if_possible(result); - infcx.tcx.erase_regions(result) -}  | 
