Skip to content

Commit 94fe30f

Browse files
committed
Treat different opaque types of the same def id as equal during coherence
1 parent 2752e32 commit 94fe30f

File tree

17 files changed

+182
-50
lines changed

17 files changed

+182
-50
lines changed

compiler/rustc_hir_analysis/src/check/dropck.rs

+4
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,10 @@ impl<'tcx> TypeRelation<'tcx> for SimpleEqRelation<'tcx> {
244244
self.tcx
245245
}
246246

247+
fn intercrate(&self) -> bool {
248+
false
249+
}
250+
247251
fn param_env(&self) -> ty::ParamEnv<'tcx> {
248252
self.param_env
249253
}

compiler/rustc_infer/src/infer/at.rs

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ impl<'tcx> InferCtxt<'tcx> {
8181
.normalize_fn_sig_for_diagnostic
8282
.as_ref()
8383
.map(|f| f.clone()),
84+
intercrate: self.intercrate,
8485
}
8586
}
8687
}

compiler/rustc_infer/src/infer/combine.rs

+9
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,11 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
521521
fn tcx(&self) -> TyCtxt<'tcx> {
522522
self.infcx.tcx
523523
}
524+
525+
fn intercrate(&self) -> bool {
526+
self.infcx.intercrate
527+
}
528+
524529
fn param_env(&self) -> ty::ParamEnv<'tcx> {
525530
self.param_env
526531
}
@@ -799,6 +804,10 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
799804
self.infcx.tcx
800805
}
801806

807+
fn intercrate(&self) -> bool {
808+
self.infcx.intercrate
809+
}
810+
802811
fn param_env(&self) -> ty::ParamEnv<'tcx> {
803812
self.param_env
804813
}

compiler/rustc_infer/src/infer/equate.rs

+4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
3232
self.fields.tcx()
3333
}
3434

35+
fn intercrate(&self) -> bool {
36+
self.fields.infcx.intercrate
37+
}
38+
3539
fn param_env(&self) -> ty::ParamEnv<'tcx> {
3640
self.fields.param_env
3741
}

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -2937,6 +2937,10 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
29372937
self.0.tcx
29382938
}
29392939

2940+
fn intercrate(&self) -> bool {
2941+
self.0.intercrate
2942+
}
2943+
29402944
fn param_env(&self) -> ty::ParamEnv<'tcx> {
29412945
// Unused, only for consts which we treat as always equal
29422946
ty::ParamEnv::empty()

compiler/rustc_infer/src/infer/glb.rs

+4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
3030
"Glb"
3131
}
3232

33+
fn intercrate(&self) -> bool {
34+
self.fields.infcx.intercrate
35+
}
36+
3337
fn tcx(&self) -> TyCtxt<'tcx> {
3438
self.fields.tcx()
3539
}

compiler/rustc_infer/src/infer/lub.rs

+4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
3030
"Lub"
3131
}
3232

33+
fn intercrate(&self) -> bool {
34+
self.fields.infcx.intercrate
35+
}
36+
3337
fn tcx(&self) -> TyCtxt<'tcx> {
3438
self.fields.tcx()
3539
}

compiler/rustc_infer/src/infer/mod.rs

+29
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,26 @@ pub struct InferCtxt<'tcx> {
337337

338338
normalize_fn_sig_for_diagnostic:
339339
Option<Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>,
340+
341+
/// During coherence we have to assume that other crates may add
342+
/// additional impls which we currently don't know about.
343+
///
344+
/// To deal with this evaluation should be conservative
345+
/// and consider the possibility of impls from outside this crate.
346+
/// This comes up primarily when resolving ambiguity. Imagine
347+
/// there is some trait reference `$0: Bar` where `$0` is an
348+
/// inference variable. If `intercrate` is true, then we can never
349+
/// say for sure that this reference is not implemented, even if
350+
/// there are *no impls at all for `Bar`*, because `$0` could be
351+
/// bound to some type that in a downstream crate that implements
352+
/// `Bar`.
353+
///
354+
/// Outside of coherence we set this to false because we are only
355+
/// interested in types that the user could actually have written.
356+
/// In other words, we consider `$0: Bar` to be unimplemented if
357+
/// there is no type that the user could *actually name* that
358+
/// would satisfy it. This avoids crippling inference, basically.
359+
pub intercrate: bool,
340360
}
341361

342362
/// See the `error_reporting` module for more details.
@@ -554,6 +574,7 @@ pub struct InferCtxtBuilder<'tcx> {
554574
considering_regions: bool,
555575
normalize_fn_sig_for_diagnostic:
556576
Option<Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>,
577+
intercrate: bool,
557578
}
558579

559580
pub trait TyCtxtInferExt<'tcx> {
@@ -567,6 +588,7 @@ impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
567588
defining_use_anchor: DefiningAnchor::Error,
568589
considering_regions: true,
569590
normalize_fn_sig_for_diagnostic: None,
591+
intercrate: false,
570592
}
571593
}
572594
}
@@ -583,6 +605,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
583605
self
584606
}
585607

608+
pub fn intercrate(mut self) -> Self {
609+
self.intercrate = true;
610+
self
611+
}
612+
586613
pub fn ignoring_regions(mut self) -> Self {
587614
self.considering_regions = false;
588615
self
@@ -622,6 +649,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
622649
defining_use_anchor,
623650
considering_regions,
624651
ref normalize_fn_sig_for_diagnostic,
652+
intercrate,
625653
} = *self;
626654
InferCtxt {
627655
tcx,
@@ -641,6 +669,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
641669
normalize_fn_sig_for_diagnostic: normalize_fn_sig_for_diagnostic
642670
.as_ref()
643671
.map(|f| f.clone()),
672+
intercrate,
644673
}
645674
}
646675
}

compiler/rustc_infer/src/infer/nll_relate/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,10 @@ where
531531
self.infcx.tcx
532532
}
533533

534+
fn intercrate(&self) -> bool {
535+
self.infcx.intercrate
536+
}
537+
534538
fn param_env(&self) -> ty::ParamEnv<'tcx> {
535539
self.delegate.param_env()
536540
}
@@ -898,6 +902,10 @@ where
898902
self.infcx.tcx
899903
}
900904

905+
fn intercrate(&self) -> bool {
906+
self.infcx.intercrate
907+
}
908+
901909
fn param_env(&self) -> ty::ParamEnv<'tcx> {
902910
self.delegate.param_env()
903911
}

compiler/rustc_infer/src/infer/outlives/test_type_match.rs

+5
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,11 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
136136
fn tag(&self) -> &'static str {
137137
"Match"
138138
}
139+
140+
fn intercrate(&self) -> bool {
141+
false
142+
}
143+
139144
fn tcx(&self) -> TyCtxt<'tcx> {
140145
self.tcx
141146
}

compiler/rustc_infer/src/infer/sub.rs

+5
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
3535
fn tag(&self) -> &'static str {
3636
"Sub"
3737
}
38+
39+
fn intercrate(&self) -> bool {
40+
self.fields.infcx.intercrate
41+
}
42+
3843
fn tcx(&self) -> TyCtxt<'tcx> {
3944
self.fields.infcx.tcx
4045
}

compiler/rustc_middle/src/ty/_match.rs

+5
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
3636
fn tcx(&self) -> TyCtxt<'tcx> {
3737
self.tcx
3838
}
39+
40+
fn intercrate(&self) -> bool {
41+
false
42+
}
43+
3944
fn param_env(&self) -> ty::ParamEnv<'tcx> {
4045
self.param_env
4146
}

compiler/rustc_middle/src/ty/relate.rs

+18-10
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ pub enum Cause {
2323
pub trait TypeRelation<'tcx>: Sized {
2424
fn tcx(&self) -> TyCtxt<'tcx>;
2525

26+
fn intercrate(&self) -> bool;
27+
2628
fn param_env(&self) -> ty::ParamEnv<'tcx>;
2729

2830
/// Returns a static string we can use for printouts.
@@ -562,16 +564,22 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
562564
(&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs))
563565
if a_def_id == b_def_id =>
564566
{
565-
let opt_variances = tcx.variances_of(a_def_id);
566-
let substs = relate_substs_with_variances(
567-
relation,
568-
a_def_id,
569-
opt_variances,
570-
a_substs,
571-
b_substs,
572-
false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
573-
)?;
574-
Ok(tcx.mk_opaque(a_def_id, substs))
567+
if relation.intercrate() {
568+
// During coherence, opaque types should be treated as equal to each other, even if their generic params
569+
// differ, as they could resolve to the same hidden type, even for different generic params.
570+
Ok(a)
571+
} else {
572+
let opt_variances = tcx.variances_of(a_def_id);
573+
let substs = relate_substs_with_variances(
574+
relation,
575+
a_def_id,
576+
opt_variances,
577+
a_substs,
578+
b_substs,
579+
false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle
580+
)?;
581+
Ok(tcx.mk_opaque(a_def_id, substs))
582+
}
575583
}
576584

577585
_ => Err(TypeError::Sorts(expected_found(relation, a, b))),

compiler/rustc_trait_selection/src/traits/coherence.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,9 @@ pub fn overlapping_impls<'tcx>(
9494
return None;
9595
}
9696

97-
let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build();
98-
let selcx = &mut SelectionContext::intercrate(&infcx);
97+
let infcx =
98+
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).intercrate().build();
99+
let selcx = &mut SelectionContext::new(&infcx);
99100
let overlaps =
100101
overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).is_some();
101102
if !overlaps {
@@ -105,8 +106,9 @@ pub fn overlapping_impls<'tcx>(
105106
// In the case where we detect an error, run the check again, but
106107
// this time tracking intercrate ambiguity causes for better
107108
// diagnostics. (These take time and can lead to false errors.)
108-
let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build();
109-
let selcx = &mut SelectionContext::intercrate(&infcx);
109+
let infcx =
110+
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).intercrate().build();
111+
let selcx = &mut SelectionContext::new(&infcx);
110112
selcx.enable_tracking_intercrate_ambiguity_causes();
111113
Some(overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).unwrap())
112114
}

0 commit comments

Comments
 (0)