Skip to content

Commit c54dd33

Browse files
committed
Don't let thte diagnostic leak the inner types of opaque types
1 parent 8486448 commit c54dd33

3 files changed

Lines changed: 64 additions & 7 deletions

File tree

‎compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs‎

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use std::ops::ControlFlow;
22

3-
use rustc_hir::LangItem;
3+
use rustc_hir::{self as hir, LangItem};
44
use rustc_infer::infer::InferCtxt;
5-
use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause};
5+
use rustc_infer::traits::solve::{BuiltinImplSource, CandidateSource, GoalSource, MaybeCause};
66
use rustc_infer::traits::{
77
self, MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode,
88
PredicateObligation, SelectionError,
@@ -248,6 +248,55 @@ impl<'tcx> BestObligation<'tcx> {
248248
candidates
249249
}
250250

251+
fn is_opaque_auto_trait_candidate(
252+
&self,
253+
tcx: TyCtxt<'tcx>,
254+
candidate: &inspect::InspectCandidate<'_, 'tcx>,
255+
pred: ty::Predicate<'tcx>,
256+
) -> bool {
257+
self.is_builtin_misc_trait_candidate(candidate)
258+
&& self.is_positive_auto_trait_predicate_with_opaque_self(tcx, pred)
259+
}
260+
261+
fn is_builtin_misc_trait_candidate(
262+
&self,
263+
candidate: &inspect::InspectCandidate<'_, 'tcx>,
264+
) -> bool {
265+
matches!(
266+
candidate.kind(),
267+
inspect::ProbeKind::TraitCandidate {
268+
source: CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
269+
result: _,
270+
}
271+
)
272+
}
273+
274+
fn is_positive_auto_trait_predicate_with_opaque_self(
275+
&self,
276+
tcx: TyCtxt<'tcx>,
277+
pred: ty::Predicate<'tcx>,
278+
) -> bool {
279+
let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) =
280+
pred.kind().skip_binder()
281+
else {
282+
return false;
283+
};
284+
285+
if trait_pred.polarity != ty::PredicatePolarity::Positive
286+
|| !tcx.trait_is_auto(trait_pred.def_id())
287+
{
288+
return false;
289+
}
290+
291+
let ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id, .. }, .. }) =
292+
trait_pred.self_ty().kind()
293+
else {
294+
return false;
295+
};
296+
297+
!matches!(tcx.opaque_ty_origin(*def_id), hir::OpaqueTyOrigin::AsyncFn { .. })
298+
}
299+
251300
/// HACK: We walk the nested obligations for a well-formed arg manually,
252301
/// since there's nontrivial logic in `wf.rs` to set up an obligation cause.
253302
/// Ideally we'd be able to track this better.
@@ -447,6 +496,13 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
447496
return ControlFlow::Break(self.obligation.clone());
448497
}
449498

499+
// Don't walk into opaque auto trait candidates, as doing so would expose
500+
// the opaque's hidden type in diagnostics outside of its defining scope.
501+
if self.is_opaque_auto_trait_candidate(tcx, candidate, pred) {
502+
trace!("opaque auto trait candidate -> exit");
503+
return ControlFlow::Break(self.obligation.clone());
504+
}
505+
450506
// FIXME: Also, what about considering >1 layer up the stack? May be necessary
451507
// for normalizes-to.
452508
let child_mode = match pred.kind().skip_binder() {

‎tests/ui/impl-trait/auto-trait-leakage/opaque-hidden-ty-inference.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ where
2323
// Proving `impl Sized: Unpin` must not constrain `NameMe<T>`
2424
// to the foreign closure hidden inside `define`.
2525
let opaque = require_auto(define::<T>());
26-
//~^ ERROR type annotations needed
26+
//~^ ERROR `impl Sized` cannot be unpinned
2727
let closure;
2828
loop {}
2929
return closure;
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
error[E0283]: type annotations needed: cannot satisfy `impl Sized: Unpin`
1+
error[E0277]: `impl Sized` cannot be unpinned
22
--> $DIR/opaque-hidden-ty-inference.rs:25:31
33
|
44
LL | let opaque = require_auto(define::<T>());
5-
| ------------ ^^^^^^^^^^^^^
5+
| ------------ ^^^^^^^^^^^^^ the trait `Unpin` is not implemented for `impl Sized`
66
| |
77
| required by a bound introduced by this call
88
|
9-
= note: cannot satisfy `impl Sized: Unpin`
9+
= note: consider using the `pin!` macro
10+
consider using `Box::pin` if you need to access the pinned value outside of the current scope
1011
note: required by a bound in `require_auto`
1112
--> $DIR/opaque-hidden-ty-inference.rs:12:20
1213
|
@@ -15,4 +16,4 @@ LL | fn require_auto<T: Unpin>(x: T) -> T {
1516

1617
error: aborting due to 1 previous error
1718

18-
For more information about this error, try `rustc --explain E0283`.
19+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)