Skip to content

Commit 6c62b42

Browse files
authored
Rollup merge of #118089 - lcnr:intercrate-ambig-msg, r=compiler-errors
intercrate_ambiguity_causes: handle self ty infer + reservation impls r? `@compiler-errors`
2 parents ca246d3 + 35c8a37 commit 6c62b42

File tree

11 files changed

+104
-43
lines changed

11 files changed

+104
-43
lines changed

compiler/rustc_trait_selection/src/solve/assembly/mod.rs

+19-16
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ pub(super) trait GoalKind<'tcx>:
110110
ecx: &mut EvalCtxt<'_, 'tcx>,
111111
goal: Goal<'tcx, Self>,
112112
impl_def_id: DefId,
113-
) -> QueryResult<'tcx>;
113+
) -> Result<Candidate<'tcx>, NoSolution>;
114114

115115
/// If the predicate contained an error, we want to avoid emitting unnecessary trait
116116
/// errors but still want to emit errors for other trait goals. We have some special
@@ -263,7 +263,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
263263
) -> Vec<Candidate<'tcx>> {
264264
debug_assert_eq!(goal, self.resolve_vars_if_possible(goal));
265265
if let Some(ambig) = self.assemble_self_ty_infer_ambiguity_response(goal) {
266-
return ambig;
266+
return vec![ambig];
267267
}
268268

269269
let mut candidates = self.assemble_candidates_via_self_ty(goal, 0);
@@ -288,15 +288,20 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
288288
fn assemble_self_ty_infer_ambiguity_response<G: GoalKind<'tcx>>(
289289
&mut self,
290290
goal: Goal<'tcx, G>,
291-
) -> Option<Vec<Candidate<'tcx>>> {
292-
goal.predicate.self_ty().is_ty_var().then(|| {
293-
vec![Candidate {
294-
source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
295-
result: self
296-
.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
297-
.unwrap(),
298-
}]
299-
})
291+
) -> Option<Candidate<'tcx>> {
292+
if goal.predicate.self_ty().is_ty_var() {
293+
debug!("adding self_ty_infer_ambiguity_response");
294+
let source = CandidateSource::BuiltinImpl(BuiltinImplSource::Misc);
295+
let result = self
296+
.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
297+
.unwrap();
298+
let mut dummy_probe = self.inspect.new_probe();
299+
dummy_probe.probe_kind(ProbeKind::TraitCandidate { source, result: Ok(result) });
300+
self.inspect.finish_probe(dummy_probe);
301+
Some(Candidate { source, result })
302+
} else {
303+
None
304+
}
300305
}
301306

302307
/// Assemble candidates which apply to the self type. This only looks at candidate which
@@ -310,7 +315,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
310315
) -> Vec<Candidate<'tcx>> {
311316
debug_assert_eq!(goal, self.resolve_vars_if_possible(goal));
312317
if let Some(ambig) = self.assemble_self_ty_infer_ambiguity_response(goal) {
313-
return ambig;
318+
return vec![ambig];
314319
}
315320

316321
let mut candidates = Vec::new();
@@ -395,8 +400,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
395400
if let Some(impls_for_type) = trait_impls.non_blanket_impls().get(&simp) {
396401
for &impl_def_id in impls_for_type {
397402
match G::consider_impl_candidate(self, goal, impl_def_id) {
398-
Ok(result) => candidates
399-
.push(Candidate { source: CandidateSource::Impl(impl_def_id), result }),
403+
Ok(candidate) => candidates.push(candidate),
400404
Err(NoSolution) => (),
401405
}
402406
}
@@ -514,8 +518,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
514518
let trait_impls = tcx.trait_impls_of(goal.predicate.trait_def_id(tcx));
515519
for &impl_def_id in trait_impls.blanket_impls() {
516520
match G::consider_impl_candidate(self, goal, impl_def_id) {
517-
Ok(result) => candidates
518-
.push(Candidate { source: CandidateSource::Impl(impl_def_id), result }),
521+
Ok(candidate) => candidates.push(candidate),
519522
Err(NoSolution) => (),
520523
}
521524
}

compiler/rustc_trait_selection/src/solve/eval_ctxt/probe.rs

+34-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
use crate::solve::assembly::Candidate;
2+
13
use super::EvalCtxt;
2-
use rustc_middle::traits::solve::{inspect, CandidateSource, QueryResult};
4+
use rustc_middle::traits::{
5+
query::NoSolution,
6+
solve::{inspect, CandidateSource, QueryResult},
7+
};
38
use std::marker::PhantomData;
49

510
pub(in crate::solve) struct ProbeCtxt<'me, 'a, 'tcx, F, T> {
@@ -36,6 +41,23 @@ where
3641
}
3742
}
3843

44+
pub(in crate::solve) struct TraitProbeCtxt<'me, 'a, 'tcx, F> {
45+
cx: ProbeCtxt<'me, 'a, 'tcx, F, QueryResult<'tcx>>,
46+
source: CandidateSource,
47+
}
48+
49+
impl<'tcx, F> TraitProbeCtxt<'_, '_, 'tcx, F>
50+
where
51+
F: FnOnce(&QueryResult<'tcx>) -> inspect::ProbeKind<'tcx>,
52+
{
53+
pub(in crate::solve) fn enter(
54+
self,
55+
f: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>,
56+
) -> Result<Candidate<'tcx>, NoSolution> {
57+
self.cx.enter(|ecx| f(ecx)).map(|result| Candidate { source: self.source, result })
58+
}
59+
}
60+
3961
impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
4062
/// `probe_kind` is only called when proof tree building is enabled so it can be
4163
/// as expensive as necessary to output the desired information.
@@ -69,20 +91,18 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
6991
pub(in crate::solve) fn probe_trait_candidate(
7092
&mut self,
7193
source: CandidateSource,
72-
) -> ProbeCtxt<
73-
'_,
74-
'a,
75-
'tcx,
76-
impl FnOnce(&QueryResult<'tcx>) -> inspect::ProbeKind<'tcx>,
77-
QueryResult<'tcx>,
78-
> {
79-
ProbeCtxt {
80-
ecx: self,
81-
probe_kind: move |result: &QueryResult<'tcx>| inspect::ProbeKind::TraitCandidate {
82-
source,
83-
result: *result,
94+
) -> TraitProbeCtxt<'_, 'a, 'tcx, impl FnOnce(&QueryResult<'tcx>) -> inspect::ProbeKind<'tcx>>
95+
{
96+
TraitProbeCtxt {
97+
cx: ProbeCtxt {
98+
ecx: self,
99+
probe_kind: move |result: &QueryResult<'tcx>| inspect::ProbeKind::TraitCandidate {
100+
source,
101+
result: *result,
102+
},
103+
_result: PhantomData,
84104
},
85-
_result: PhantomData,
105+
source,
86106
}
87107
}
88108
}

compiler/rustc_trait_selection/src/solve/project_goals/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::traits::{check_args_compatible, specialization_graph};
22

3-
use super::assembly::{self, structural_traits};
3+
use super::assembly::{self, structural_traits, Candidate};
44
use super::EvalCtxt;
55
use rustc_hir::def::DefKind;
66
use rustc_hir::def_id::DefId;
@@ -154,7 +154,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
154154
ecx: &mut EvalCtxt<'_, 'tcx>,
155155
goal: Goal<'tcx, ProjectionPredicate<'tcx>>,
156156
impl_def_id: DefId,
157-
) -> QueryResult<'tcx> {
157+
) -> Result<Candidate<'tcx>, NoSolution> {
158158
let tcx = ecx.tcx();
159159

160160
let goal_trait_ref = goal.predicate.projection_ty.trait_ref(tcx);

compiler/rustc_trait_selection/src/solve/trait_goals.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
//! Dealing with trait goals, i.e. `T: Trait<'a, U>`.
22
3-
use super::assembly::{self, structural_traits};
3+
use super::assembly::{self, structural_traits, Candidate};
44
use super::{EvalCtxt, SolverMode};
55
use rustc_hir::def_id::DefId;
66
use rustc_hir::{LangItem, Movability};
77
use rustc_infer::traits::query::NoSolution;
88
use rustc_middle::traits::solve::inspect::ProbeKind;
9-
use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, QueryResult};
9+
use rustc_middle::traits::solve::{
10+
CandidateSource, CanonicalResponse, Certainty, Goal, QueryResult,
11+
};
1012
use rustc_middle::traits::{BuiltinImplSource, Reveal};
1113
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, TreatProjections};
1214
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
@@ -38,7 +40,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
3840
ecx: &mut EvalCtxt<'_, 'tcx>,
3941
goal: Goal<'tcx, TraitPredicate<'tcx>>,
4042
impl_def_id: DefId,
41-
) -> QueryResult<'tcx> {
43+
) -> Result<Candidate<'tcx>, NoSolution> {
4244
let tcx = ecx.tcx();
4345

4446
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
@@ -63,7 +65,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
6365
},
6466
};
6567

66-
ecx.probe_misc_candidate("impl").enter(|ecx| {
68+
ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
6769
let impl_args = ecx.fresh_args_for_item(impl_def_id);
6870
let impl_trait_ref = impl_trait_ref.instantiate(tcx, impl_args);
6971

compiler/rustc_trait_selection/src/traits/coherence.rs

+23-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE};
2525
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt};
2626
use rustc_infer::traits::{util, TraitEngine};
2727
use rustc_middle::traits::query::NoSolution;
28-
use rustc_middle::traits::solve::{Certainty, Goal};
28+
use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal};
2929
use rustc_middle::traits::specialization_graph::OverlapMode;
3030
use rustc_middle::traits::DefiningAnchor;
3131
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
@@ -1025,6 +1025,28 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a> {
10251025
_ => return ControlFlow::Continue(()),
10261026
};
10271027

1028+
// Add ambiguity causes for reservation impls.
1029+
for cand in goal.candidates() {
1030+
if let inspect::ProbeKind::TraitCandidate {
1031+
source: CandidateSource::Impl(def_id),
1032+
result: Ok(_),
1033+
} = cand.kind()
1034+
{
1035+
if let ty::ImplPolarity::Reservation = infcx.tcx.impl_polarity(def_id) {
1036+
let value = infcx
1037+
.tcx
1038+
.get_attr(def_id, sym::rustc_reservation_impl)
1039+
.and_then(|a| a.value_str());
1040+
if let Some(value) = value {
1041+
self.causes.insert(IntercrateAmbiguityCause::ReservationImpl {
1042+
message: value.to_string(),
1043+
});
1044+
}
1045+
}
1046+
}
1047+
}
1048+
1049+
// Add ambiguity causes for unknowable goals.
10281050
let mut ambiguity_cause = None;
10291051
for cand in goal.candidates() {
10301052
// FIXME: boiiii, using string comparisions here sure is scuffed.

tests/ui/impl-trait/auto-trait-coherence.next.stderr

-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ LL | impl<T: Send> AnotherTrait for T {}
66
...
77
LL | impl AnotherTrait for D<OpaqueType> {
88
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
9-
|
10-
= note: upstream crates may add a new impl of trait `std::marker::Send` for type `OpaqueType` in future versions
119

1210
error: aborting due to previous error
1311

tests/ui/never_type/never-from-impl-is-reserved.stderr renamed to tests/ui/never_type/never-from-impl-is-reserved.current.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0119]: conflicting implementations of trait `MyTrait` for type `MyFoo`
2-
--> $DIR/never-from-impl-is-reserved.rs:10:1
2+
--> $DIR/never-from-impl-is-reserved.rs:13:1
33
|
44
LL | impl MyTrait for MyFoo {}
55
| ---------------------- first implementation here
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0119]: conflicting implementations of trait `MyTrait` for type `MyFoo`
2+
--> $DIR/never-from-impl-is-reserved.rs:13:1
3+
|
4+
LL | impl MyTrait for MyFoo {}
5+
| ---------------------- first implementation here
6+
LL | // This will conflict with the first impl if we impl `for<T> T: From<!>`.
7+
LL | impl<T> MyTrait for T where T: From<!> {}
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyFoo`
9+
|
10+
= note: permitting this impl would forbid us from adding `impl<T> From<!> for T` later; see rust-lang/rust#64715 for details
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0119`.

tests/ui/never_type/never-from-impl-is-reserved.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// check that the `for<T> T: From<!>` impl is reserved
22

3+
// revisions: current next
4+
//[next] compile-flags: -Ztrait-solver=next-coherence
5+
36
#![feature(never_type)]
47

58
pub struct MyFoo;

tests/ui/traits/new-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr

-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@ LL | impl<T: Copy> Trait for T {}
66
LL | struct LocalTy;
77
LL | impl Trait for <LocalTy as Overflow>::Assoc {}
88
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<LocalTy as Overflow>::Assoc`
9-
|
10-
= note: downstream crates may implement trait `std::marker::Sized` for type `<LocalTy as Overflow>::Assoc`
11-
= note: downstream crates may implement trait `std::marker::Copy` for type `<LocalTy as Overflow>::Assoc`
129

1310
error: aborting due to previous error
1411

tests/ui/traits/reservation-impl/coherence-conflict.next.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ LL | impl OtherTrait for () {}
55
| ---------------------- first implementation here
66
LL | impl<T: MyTrait> OtherTrait for T {}
77
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
8+
|
9+
= note: this impl is reserved
810

911
error: aborting due to previous error
1012

0 commit comments

Comments
 (0)