X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=compiler%2Frustc_trait_selection%2Fsrc%2Ftraits%2Fcoherence.rs;h=f62ccb99df5ebf12118cfff4e460caaed5eec5e5;hb=c436930f91a4befefa602f2d64d06fc9613d507b;hp=9983438233e1ef129275b506f53ab82d1f57a2e6;hpb=47ba93596586783efd41df7b8ea84f4f1e37f923;p=rust.git diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 9983438233e..38e2500da9b 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -10,14 +10,14 @@ use crate::traits::util::impl_subject_and_oblig; use crate::traits::SkipLeakCheck; use crate::traits::{ - self, FulfillmentContext, Normalized, Obligation, ObligationCause, PredicateObligation, - PredicateObligations, SelectionContext, + self, Normalized, Obligation, ObligationCause, PredicateObligation, PredicateObligations, + SelectionContext, }; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::Diagnostic; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::{util, TraitEngine}; +use rustc_infer::traits::util; use rustc_middle::traits::specialization_graph::OverlapMode; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_middle::ty::subst::Subst; @@ -302,13 +302,18 @@ fn negative_impl<'cx, 'tcx>( let impl_env = tcx.param_env(impl1_def_id); let subject1 = match traits::fully_normalize( &infcx, - FulfillmentContext::new(), ObligationCause::dummy(), impl_env, tcx.impl_subject(impl1_def_id), ) { Ok(s) => s, - Err(err) => bug!("failed to fully normalize {:?}: {:?}", impl1_def_id, err), + Err(err) => { + tcx.sess.delay_span_bug( + tcx.def_span(impl1_def_id), + format!("failed to fully normalize {:?}: {:?}", impl1_def_id, err), + ); + return false; + } }; // Attempt to prove that impl2 applies, given all of the above. @@ -385,26 +390,15 @@ fn resolve_negative_obligation<'cx, 'tcx>( return false; }; - let mut fulfillment_cx = FulfillmentContext::new(); - fulfillment_cx.register_predicate_obligation(infcx, o); - - let errors = fulfillment_cx.select_all_or_error(infcx); - + let errors = super::fully_solve_obligation(infcx, o); if !errors.is_empty() { return false; } - // FIXME -- also add "assumed to be well formed" types into the `outlives_env` let outlives_env = OutlivesEnvironment::new(param_env); infcx.process_registered_region_obligations(outlives_env.region_bound_pairs(), param_env); - let errors = infcx.resolve_regions(&outlives_env); - - if !errors.is_empty() { - return false; - } - - true + infcx.resolve_regions(&outlives_env).is_empty() } pub fn trait_ref_is_knowable<'tcx>( @@ -703,13 +697,42 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { } } ty::Error(_) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)), - ty::Opaque(..) | ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) => { + ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) => { self.tcx.sess.delay_span_bug( DUMMY_SP, format!("ty_is_local invoked on closure or generator: {:?}", ty), ); ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)) } + ty::Opaque(..) => { + // This merits some explanation. + // Normally, opaque types are not involved when performing + // coherence checking, since it is illegal to directly + // implement a trait on an opaque type. However, we might + // end up looking at an opaque type during coherence checking + // if an opaque type gets used within another type (e.g. as + // the type of a field) when checking for auto trait or `Sized` + // impls. This requires us to decide whether or not an opaque + // type should be considered 'local' or not. + // + // We choose to treat all opaque types as non-local, even + // those that appear within the same crate. This seems + // somewhat surprising at first, but makes sense when + // you consider that opaque types are supposed to hide + // the underlying type *within the same crate*. When an + // opaque type is used from outside the module + // where it is declared, it should be impossible to observe + // anything about it other than the traits that it implements. + // + // The alternative would be to look at the underlying type + // to determine whether or not the opaque type itself should + // be considered local. However, this could make it a breaking change + // to switch the underlying ('defining') type from a local type + // to a remote type. This would violate the rule that opaque + // types should be completely opaque apart from the traits + // that they implement, so we don't use this behavior. + self.found_non_local_ty(ty) + } }; // A bit of a hack, the `OrphanChecker` is only used to visit a `TraitRef`, so // the first type we visit is always the self type.