Treat different opaque types of the same def id as equal during coherence
This commit is contained in:
parent
2752e328c9
commit
94fe30ff2f
17 changed files with 182 additions and 50 deletions
|
@ -244,6 +244,10 @@ impl<'tcx> TypeRelation<'tcx> for SimpleEqRelation<'tcx> {
|
||||||
self.tcx
|
self.tcx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn intercrate(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||||
self.param_env
|
self.param_env
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
.normalize_fn_sig_for_diagnostic
|
.normalize_fn_sig_for_diagnostic
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|f| f.clone()),
|
.map(|f| f.clone()),
|
||||||
|
intercrate: self.intercrate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -521,6 +521,11 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
|
||||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||||
self.infcx.tcx
|
self.infcx.tcx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn intercrate(&self) -> bool {
|
||||||
|
self.infcx.intercrate
|
||||||
|
}
|
||||||
|
|
||||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||||
self.param_env
|
self.param_env
|
||||||
}
|
}
|
||||||
|
@ -799,6 +804,10 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
|
||||||
self.infcx.tcx
|
self.infcx.tcx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn intercrate(&self) -> bool {
|
||||||
|
self.infcx.intercrate
|
||||||
|
}
|
||||||
|
|
||||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||||
self.param_env
|
self.param_env
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,10 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
|
||||||
self.fields.tcx()
|
self.fields.tcx()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn intercrate(&self) -> bool {
|
||||||
|
self.fields.infcx.intercrate
|
||||||
|
}
|
||||||
|
|
||||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||||
self.fields.param_env
|
self.fields.param_env
|
||||||
}
|
}
|
||||||
|
|
|
@ -2937,6 +2937,10 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
|
||||||
self.0.tcx
|
self.0.tcx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn intercrate(&self) -> bool {
|
||||||
|
self.0.intercrate
|
||||||
|
}
|
||||||
|
|
||||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||||
// Unused, only for consts which we treat as always equal
|
// Unused, only for consts which we treat as always equal
|
||||||
ty::ParamEnv::empty()
|
ty::ParamEnv::empty()
|
||||||
|
|
|
@ -30,6 +30,10 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
|
||||||
"Glb"
|
"Glb"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn intercrate(&self) -> bool {
|
||||||
|
self.fields.infcx.intercrate
|
||||||
|
}
|
||||||
|
|
||||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||||
self.fields.tcx()
|
self.fields.tcx()
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,10 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
|
||||||
"Lub"
|
"Lub"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn intercrate(&self) -> bool {
|
||||||
|
self.fields.infcx.intercrate
|
||||||
|
}
|
||||||
|
|
||||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||||
self.fields.tcx()
|
self.fields.tcx()
|
||||||
}
|
}
|
||||||
|
|
|
@ -337,6 +337,26 @@ pub struct InferCtxt<'tcx> {
|
||||||
|
|
||||||
normalize_fn_sig_for_diagnostic:
|
normalize_fn_sig_for_diagnostic:
|
||||||
Option<Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>,
|
Option<Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>,
|
||||||
|
|
||||||
|
/// During coherence we have to assume that other crates may add
|
||||||
|
/// additional impls which we currently don't know about.
|
||||||
|
///
|
||||||
|
/// To deal with this evaluation should be conservative
|
||||||
|
/// and consider the possibility of impls from outside this crate.
|
||||||
|
/// This comes up primarily when resolving ambiguity. Imagine
|
||||||
|
/// there is some trait reference `$0: Bar` where `$0` is an
|
||||||
|
/// inference variable. If `intercrate` is true, then we can never
|
||||||
|
/// say for sure that this reference is not implemented, even if
|
||||||
|
/// there are *no impls at all for `Bar`*, because `$0` could be
|
||||||
|
/// bound to some type that in a downstream crate that implements
|
||||||
|
/// `Bar`.
|
||||||
|
///
|
||||||
|
/// Outside of coherence we set this to false because we are only
|
||||||
|
/// interested in types that the user could actually have written.
|
||||||
|
/// In other words, we consider `$0: Bar` to be unimplemented if
|
||||||
|
/// there is no type that the user could *actually name* that
|
||||||
|
/// would satisfy it. This avoids crippling inference, basically.
|
||||||
|
pub intercrate: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See the `error_reporting` module for more details.
|
/// See the `error_reporting` module for more details.
|
||||||
|
@ -554,6 +574,7 @@ pub struct InferCtxtBuilder<'tcx> {
|
||||||
considering_regions: bool,
|
considering_regions: bool,
|
||||||
normalize_fn_sig_for_diagnostic:
|
normalize_fn_sig_for_diagnostic:
|
||||||
Option<Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>,
|
Option<Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>,
|
||||||
|
intercrate: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait TyCtxtInferExt<'tcx> {
|
pub trait TyCtxtInferExt<'tcx> {
|
||||||
|
@ -567,6 +588,7 @@ impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
|
||||||
defining_use_anchor: DefiningAnchor::Error,
|
defining_use_anchor: DefiningAnchor::Error,
|
||||||
considering_regions: true,
|
considering_regions: true,
|
||||||
normalize_fn_sig_for_diagnostic: None,
|
normalize_fn_sig_for_diagnostic: None,
|
||||||
|
intercrate: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -583,6 +605,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn intercrate(mut self) -> Self {
|
||||||
|
self.intercrate = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn ignoring_regions(mut self) -> Self {
|
pub fn ignoring_regions(mut self) -> Self {
|
||||||
self.considering_regions = false;
|
self.considering_regions = false;
|
||||||
self
|
self
|
||||||
|
@ -622,6 +649,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
||||||
defining_use_anchor,
|
defining_use_anchor,
|
||||||
considering_regions,
|
considering_regions,
|
||||||
ref normalize_fn_sig_for_diagnostic,
|
ref normalize_fn_sig_for_diagnostic,
|
||||||
|
intercrate,
|
||||||
} = *self;
|
} = *self;
|
||||||
InferCtxt {
|
InferCtxt {
|
||||||
tcx,
|
tcx,
|
||||||
|
@ -641,6 +669,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
||||||
normalize_fn_sig_for_diagnostic: normalize_fn_sig_for_diagnostic
|
normalize_fn_sig_for_diagnostic: normalize_fn_sig_for_diagnostic
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|f| f.clone()),
|
.map(|f| f.clone()),
|
||||||
|
intercrate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -531,6 +531,10 @@ where
|
||||||
self.infcx.tcx
|
self.infcx.tcx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn intercrate(&self) -> bool {
|
||||||
|
self.infcx.intercrate
|
||||||
|
}
|
||||||
|
|
||||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||||
self.delegate.param_env()
|
self.delegate.param_env()
|
||||||
}
|
}
|
||||||
|
@ -898,6 +902,10 @@ where
|
||||||
self.infcx.tcx
|
self.infcx.tcx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn intercrate(&self) -> bool {
|
||||||
|
self.infcx.intercrate
|
||||||
|
}
|
||||||
|
|
||||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||||
self.delegate.param_env()
|
self.delegate.param_env()
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,6 +136,11 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
|
||||||
fn tag(&self) -> &'static str {
|
fn tag(&self) -> &'static str {
|
||||||
"Match"
|
"Match"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn intercrate(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||||
self.tcx
|
self.tcx
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,11 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
|
||||||
fn tag(&self) -> &'static str {
|
fn tag(&self) -> &'static str {
|
||||||
"Sub"
|
"Sub"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn intercrate(&self) -> bool {
|
||||||
|
self.fields.infcx.intercrate
|
||||||
|
}
|
||||||
|
|
||||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||||
self.fields.infcx.tcx
|
self.fields.infcx.tcx
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,11 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
|
||||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||||
self.tcx
|
self.tcx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn intercrate(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||||
self.param_env
|
self.param_env
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@ pub enum Cause {
|
||||||
pub trait TypeRelation<'tcx>: Sized {
|
pub trait TypeRelation<'tcx>: Sized {
|
||||||
fn tcx(&self) -> TyCtxt<'tcx>;
|
fn tcx(&self) -> TyCtxt<'tcx>;
|
||||||
|
|
||||||
|
fn intercrate(&self) -> bool;
|
||||||
|
|
||||||
fn param_env(&self) -> ty::ParamEnv<'tcx>;
|
fn param_env(&self) -> ty::ParamEnv<'tcx>;
|
||||||
|
|
||||||
/// Returns a static string we can use for printouts.
|
/// Returns a static string we can use for printouts.
|
||||||
|
@ -562,6 +564,11 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
|
||||||
(&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs))
|
(&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs))
|
||||||
if a_def_id == b_def_id =>
|
if a_def_id == b_def_id =>
|
||||||
{
|
{
|
||||||
|
if relation.intercrate() {
|
||||||
|
// During coherence, opaque types should be treated as equal to each other, even if their generic params
|
||||||
|
// differ, as they could resolve to the same hidden type, even for different generic params.
|
||||||
|
Ok(a)
|
||||||
|
} else {
|
||||||
let opt_variances = tcx.variances_of(a_def_id);
|
let opt_variances = tcx.variances_of(a_def_id);
|
||||||
let substs = relate_substs_with_variances(
|
let substs = relate_substs_with_variances(
|
||||||
relation,
|
relation,
|
||||||
|
@ -573,6 +580,7 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
|
||||||
)?;
|
)?;
|
||||||
Ok(tcx.mk_opaque(a_def_id, substs))
|
Ok(tcx.mk_opaque(a_def_id, substs))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_ => Err(TypeError::Sorts(expected_found(relation, a, b))),
|
_ => Err(TypeError::Sorts(expected_found(relation, a, b))),
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,8 +94,9 @@ pub fn overlapping_impls<'tcx>(
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build();
|
let infcx =
|
||||||
let selcx = &mut SelectionContext::intercrate(&infcx);
|
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).intercrate().build();
|
||||||
|
let selcx = &mut SelectionContext::new(&infcx);
|
||||||
let overlaps =
|
let overlaps =
|
||||||
overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).is_some();
|
overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).is_some();
|
||||||
if !overlaps {
|
if !overlaps {
|
||||||
|
@ -105,8 +106,9 @@ pub fn overlapping_impls<'tcx>(
|
||||||
// In the case where we detect an error, run the check again, but
|
// In the case where we detect an error, run the check again, but
|
||||||
// this time tracking intercrate ambiguity causes for better
|
// this time tracking intercrate ambiguity causes for better
|
||||||
// diagnostics. (These take time and can lead to false errors.)
|
// diagnostics. (These take time and can lead to false errors.)
|
||||||
let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build();
|
let infcx =
|
||||||
let selcx = &mut SelectionContext::intercrate(&infcx);
|
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).intercrate().build();
|
||||||
|
let selcx = &mut SelectionContext::new(&infcx);
|
||||||
selcx.enable_tracking_intercrate_ambiguity_causes();
|
selcx.enable_tracking_intercrate_ambiguity_causes();
|
||||||
Some(overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).unwrap())
|
Some(overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).unwrap())
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,25 +110,6 @@ pub struct SelectionContext<'cx, 'tcx> {
|
||||||
/// require themselves.
|
/// require themselves.
|
||||||
freshener: TypeFreshener<'cx, 'tcx>,
|
freshener: TypeFreshener<'cx, 'tcx>,
|
||||||
|
|
||||||
/// During coherence we have to assume that other crates may add
|
|
||||||
/// additional impls which we currently don't know about.
|
|
||||||
///
|
|
||||||
/// To deal with this evaluation should be conservative
|
|
||||||
/// and consider the possibility of impls from outside this crate.
|
|
||||||
/// This comes up primarily when resolving ambiguity. Imagine
|
|
||||||
/// there is some trait reference `$0: Bar` where `$0` is an
|
|
||||||
/// inference variable. If `intercrate` is true, then we can never
|
|
||||||
/// say for sure that this reference is not implemented, even if
|
|
||||||
/// there are *no impls at all for `Bar`*, because `$0` could be
|
|
||||||
/// bound to some type that in a downstream crate that implements
|
|
||||||
/// `Bar`.
|
|
||||||
///
|
|
||||||
/// Outside of coherence we set this to false because we are only
|
|
||||||
/// interested in types that the user could actually have written.
|
|
||||||
/// In other words, we consider `$0: Bar` to be unimplemented if
|
|
||||||
/// there is no type that the user could *actually name* that
|
|
||||||
/// would satisfy it. This avoids crippling inference, basically.
|
|
||||||
intercrate: bool,
|
|
||||||
/// If `intercrate` is set, we remember predicates which were
|
/// If `intercrate` is set, we remember predicates which were
|
||||||
/// considered ambiguous because of impls potentially added in other crates.
|
/// considered ambiguous because of impls potentially added in other crates.
|
||||||
/// This is used in coherence to give improved diagnostics.
|
/// This is used in coherence to give improved diagnostics.
|
||||||
|
@ -226,16 +207,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
SelectionContext {
|
SelectionContext {
|
||||||
infcx,
|
infcx,
|
||||||
freshener: infcx.freshener_keep_static(),
|
freshener: infcx.freshener_keep_static(),
|
||||||
intercrate: false,
|
|
||||||
intercrate_ambiguity_causes: None,
|
intercrate_ambiguity_causes: None,
|
||||||
query_mode: TraitQueryMode::Standard,
|
query_mode: TraitQueryMode::Standard,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn intercrate(infcx: &'cx InferCtxt<'tcx>) -> SelectionContext<'cx, 'tcx> {
|
|
||||||
SelectionContext { intercrate: true, ..SelectionContext::new(infcx) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_query_mode(
|
pub fn with_query_mode(
|
||||||
infcx: &'cx InferCtxt<'tcx>,
|
infcx: &'cx InferCtxt<'tcx>,
|
||||||
query_mode: TraitQueryMode,
|
query_mode: TraitQueryMode,
|
||||||
|
@ -247,7 +223,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
/// Enables tracking of intercrate ambiguity causes. See
|
/// Enables tracking of intercrate ambiguity causes. See
|
||||||
/// the documentation of [`Self::intercrate_ambiguity_causes`] for more.
|
/// the documentation of [`Self::intercrate_ambiguity_causes`] for more.
|
||||||
pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) {
|
pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) {
|
||||||
assert!(self.intercrate);
|
assert!(self.is_intercrate());
|
||||||
assert!(self.intercrate_ambiguity_causes.is_none());
|
assert!(self.intercrate_ambiguity_causes.is_none());
|
||||||
self.intercrate_ambiguity_causes = Some(FxIndexSet::default());
|
self.intercrate_ambiguity_causes = Some(FxIndexSet::default());
|
||||||
debug!("selcx: enable_tracking_intercrate_ambiguity_causes");
|
debug!("selcx: enable_tracking_intercrate_ambiguity_causes");
|
||||||
|
@ -257,7 +233,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
/// was enabled and disables tracking at the same time. If
|
/// was enabled and disables tracking at the same time. If
|
||||||
/// tracking is not enabled, just returns an empty vector.
|
/// tracking is not enabled, just returns an empty vector.
|
||||||
pub fn take_intercrate_ambiguity_causes(&mut self) -> FxIndexSet<IntercrateAmbiguityCause> {
|
pub fn take_intercrate_ambiguity_causes(&mut self) -> FxIndexSet<IntercrateAmbiguityCause> {
|
||||||
assert!(self.intercrate);
|
assert!(self.is_intercrate());
|
||||||
self.intercrate_ambiguity_causes.take().unwrap_or_default()
|
self.intercrate_ambiguity_causes.take().unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +246,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_intercrate(&self) -> bool {
|
pub fn is_intercrate(&self) -> bool {
|
||||||
self.intercrate
|
self.infcx.intercrate
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -751,7 +727,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
previous_stack: TraitObligationStackList<'o, 'tcx>,
|
previous_stack: TraitObligationStackList<'o, 'tcx>,
|
||||||
mut obligation: TraitObligation<'tcx>,
|
mut obligation: TraitObligation<'tcx>,
|
||||||
) -> Result<EvaluationResult, OverflowError> {
|
) -> Result<EvaluationResult, OverflowError> {
|
||||||
if !self.intercrate
|
if !self.is_intercrate()
|
||||||
&& obligation.is_global()
|
&& obligation.is_global()
|
||||||
&& obligation.param_env.caller_bounds().iter().all(|bound| bound.needs_subst())
|
&& obligation.param_env.caller_bounds().iter().all(|bound| bound.needs_subst())
|
||||||
{
|
{
|
||||||
|
@ -1014,7 +990,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
// mode, so don't do any caching. In particular, we might
|
// mode, so don't do any caching. In particular, we might
|
||||||
// re-use the same `InferCtxt` with both an intercrate
|
// re-use the same `InferCtxt` with both an intercrate
|
||||||
// and non-intercrate `SelectionContext`
|
// and non-intercrate `SelectionContext`
|
||||||
if self.intercrate {
|
if self.is_intercrate() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1044,7 +1020,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
// mode, so don't do any caching. In particular, we might
|
// mode, so don't do any caching. In particular, we might
|
||||||
// re-use the same `InferCtxt` with both an intercrate
|
// re-use the same `InferCtxt` with both an intercrate
|
||||||
// and non-intercrate `SelectionContext`
|
// and non-intercrate `SelectionContext`
|
||||||
if self.intercrate {
|
if self.is_intercrate() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1225,9 +1201,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Result<(), Conflict> {
|
fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Result<(), Conflict> {
|
||||||
debug!("is_knowable(intercrate={:?})", self.intercrate);
|
debug!("is_knowable(intercrate={:?})", self.is_intercrate());
|
||||||
|
|
||||||
if !self.intercrate || stack.obligation.polarity() == ty::ImplPolarity::Negative {
|
if !self.is_intercrate() || stack.obligation.polarity() == ty::ImplPolarity::Negative {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1258,7 +1234,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
// the master cache. Since coherence executes pretty quickly,
|
// the master cache. Since coherence executes pretty quickly,
|
||||||
// it's not worth going to more trouble to increase the
|
// it's not worth going to more trouble to increase the
|
||||||
// hit-rate, I don't think.
|
// hit-rate, I don't think.
|
||||||
if self.intercrate {
|
if self.is_intercrate() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1275,7 +1251,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
// mode, so don't do any caching. In particular, we might
|
// mode, so don't do any caching. In particular, we might
|
||||||
// re-use the same `InferCtxt` with both an intercrate
|
// re-use the same `InferCtxt` with both an intercrate
|
||||||
// and non-intercrate `SelectionContext`
|
// and non-intercrate `SelectionContext`
|
||||||
if self.intercrate {
|
if self.is_intercrate() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
|
@ -1314,7 +1290,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
// mode, so don't do any caching. In particular, we might
|
// mode, so don't do any caching. In particular, we might
|
||||||
// re-use the same `InferCtxt` with both an intercrate
|
// re-use the same `InferCtxt` with both an intercrate
|
||||||
// and non-intercrate `SelectionContext`
|
// and non-intercrate `SelectionContext`
|
||||||
if self.intercrate {
|
if self.is_intercrate() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
match result {
|
match result {
|
||||||
|
@ -2192,7 +2168,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
.map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{e}`"))?;
|
.map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{e}`"))?;
|
||||||
nested_obligations.extend(obligations);
|
nested_obligations.extend(obligations);
|
||||||
|
|
||||||
if !self.intercrate
|
if !self.is_intercrate()
|
||||||
&& self.tcx().impl_polarity(impl_def_id) == ty::ImplPolarity::Reservation
|
&& self.tcx().impl_polarity(impl_def_id) == ty::ImplPolarity::Reservation
|
||||||
{
|
{
|
||||||
debug!("reservation impls only apply in intercrate mode");
|
debug!("reservation impls only apply in intercrate mode");
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
|
||||||
|
trait Foo {}
|
||||||
|
impl Foo for () {}
|
||||||
|
impl Foo for i32 {}
|
||||||
|
|
||||||
|
type Bar<T: Foo> = impl std::fmt::Debug;
|
||||||
|
fn defining_use<T: Foo>() -> Bar<T> {
|
||||||
|
42
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Bop {}
|
||||||
|
|
||||||
|
impl Bop for Bar<()> {}
|
||||||
|
|
||||||
|
// If the hidden type is the same, this is effectively a second impl for the same type.
|
||||||
|
impl Bop for Bar<i32> {}
|
||||||
|
//~^ ERROR conflicting implementations
|
||||||
|
|
||||||
|
type Barr = impl std::fmt::Debug;
|
||||||
|
fn defining_use2() -> Barr {
|
||||||
|
42
|
||||||
|
}
|
||||||
|
|
||||||
|
// Even completely different opaque types must conflict.
|
||||||
|
impl Bop for Barr {}
|
||||||
|
//~^ ERROR conflicting implementations
|
||||||
|
|
||||||
|
// And obviously the hidden type must conflict, too.
|
||||||
|
impl Bop for i32 {}
|
||||||
|
//~^ ERROR conflicting implementations
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>`
|
||||||
|
--> $DIR/impl_trait_for_same_tait.rs:17:1
|
||||||
|
|
|
||||||
|
LL | impl Bop for Bar<()> {}
|
||||||
|
| -------------------- first implementation here
|
||||||
|
...
|
||||||
|
LL | impl Bop for Bar<i32> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>`
|
||||||
|
|
||||||
|
error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>`
|
||||||
|
--> $DIR/impl_trait_for_same_tait.rs:26:1
|
||||||
|
|
|
||||||
|
LL | impl Bop for Bar<()> {}
|
||||||
|
| -------------------- first implementation here
|
||||||
|
...
|
||||||
|
LL | impl Bop for Barr {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>`
|
||||||
|
|
||||||
|
error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>`
|
||||||
|
--> $DIR/impl_trait_for_same_tait.rs:30:1
|
||||||
|
|
|
||||||
|
LL | impl Bop for Bar<()> {}
|
||||||
|
| -------------------- first implementation here
|
||||||
|
...
|
||||||
|
LL | impl Bop for i32 {}
|
||||||
|
| ^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>`
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0119`.
|
Loading…
Add table
Add a link
Reference in a new issue