|
4 | 4 | //! [trait-resolution]: https://rust-lang.github.io/rustc-guide/traits/resolution.html |
5 | 5 | //! [trait-specialization]: https://rust-lang.github.io/rustc-guide/traits/specialization.html |
6 | 6 |
|
| 7 | +use infer::CombinedSnapshot; |
7 | 8 | use hir::def_id::{DefId, LOCAL_CRATE}; |
8 | 9 | use syntax_pos::DUMMY_SP; |
9 | 10 | use traits::{self, Normalized, SelectionContext, Obligation, ObligationCause}; |
@@ -33,6 +34,17 @@ pub enum Conflict { |
33 | 34 | pub struct OverlapResult<'tcx> { |
34 | 35 | pub impl_header: ty::ImplHeader<'tcx>, |
35 | 36 | pub intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>, |
| 37 | + |
| 38 | + /// True if the overlap might've been permitted before the shift |
| 39 | + /// to universes. |
| 40 | + pub involves_placeholder: bool, |
| 41 | +} |
| 42 | + |
| 43 | +pub fn add_placeholder_note(err: &mut ::errors::DiagnosticBuilder<'_>) { |
| 44 | + err.note(&format!( |
| 45 | + "this behavior recently changed as a result of a bug fix; \ |
| 46 | + see rust-lang/rust#56105 for details" |
| 47 | + )); |
36 | 48 | } |
37 | 49 |
|
38 | 50 | /// If there are types that satisfy both impls, invokes `on_overlap` |
@@ -104,13 +116,22 @@ fn with_fresh_ty_vars<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, ' |
104 | 116 |
|
105 | 117 | /// Can both impl `a` and impl `b` be satisfied by a common type (including |
106 | 118 | /// `where` clauses)? If so, returns an `ImplHeader` that unifies the two impls. |
107 | | -fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, |
108 | | - a_def_id: DefId, |
109 | | - b_def_id: DefId) |
110 | | - -> Option<OverlapResult<'tcx>> |
111 | | -{ |
| 119 | +fn overlap<'cx, 'gcx, 'tcx>( |
| 120 | + selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, |
| 121 | + a_def_id: DefId, |
| 122 | + b_def_id: DefId, |
| 123 | +) -> Option<OverlapResult<'tcx>> { |
112 | 124 | debug!("overlap(a_def_id={:?}, b_def_id={:?})", a_def_id, b_def_id); |
113 | 125 |
|
| 126 | + selcx.infcx().probe(|snapshot| overlap_within_probe(selcx, a_def_id, b_def_id, snapshot)) |
| 127 | +} |
| 128 | + |
| 129 | +fn overlap_within_probe( |
| 130 | + selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, |
| 131 | + a_def_id: DefId, |
| 132 | + b_def_id: DefId, |
| 133 | + snapshot: &CombinedSnapshot<'_, 'tcx>, |
| 134 | +) -> Option<OverlapResult<'tcx>> { |
114 | 135 | // For the purposes of this check, we don't bring any placeholder |
115 | 136 | // types into scope; instead, we replace the generic types with |
116 | 137 | // fresh type variables, and hence we do our evaluations in an |
@@ -158,7 +179,13 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, |
158 | 179 | let impl_header = selcx.infcx().resolve_type_vars_if_possible(&a_impl_header); |
159 | 180 | let intercrate_ambiguity_causes = selcx.take_intercrate_ambiguity_causes(); |
160 | 181 | debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes); |
161 | | - Some(OverlapResult { impl_header, intercrate_ambiguity_causes }) |
| 182 | + |
| 183 | + let involves_placeholder = match selcx.infcx().region_constraints_added_in_snapshot(snapshot) { |
| 184 | + Some(true) => true, |
| 185 | + _ => false, |
| 186 | + }; |
| 187 | + |
| 188 | + Some(OverlapResult { impl_header, intercrate_ambiguity_causes, involves_placeholder }) |
162 | 189 | } |
163 | 190 |
|
164 | 191 | pub fn trait_ref_is_knowable<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, |
|
0 commit comments