From fb12f40f3b157b0f7dafe393b09bbdcf2e156c11 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 30 Jul 2022 00:41:39 +0000 Subject: [PATCH] Do not leak type variables from opaque type relation --- compiler/rustc_infer/src/infer/sub.rs | 17 ++++++++++++++--- src/test/ui/impl-trait/issue-99914.rs | 13 +++++++++++++ src/test/ui/impl-trait/issue-99914.stderr | 21 +++++++++++++++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/impl-trait/issue-99914.rs create mode 100644 src/test/ui/impl-trait/issue-99914.stderr diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index b27571275b7..b7eab5d4328 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -4,6 +4,7 @@ use crate::infer::combine::ConstEquateRelation; use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::traits::Obligation; +use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::TyVar; @@ -141,17 +142,27 @@ fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { Ok(infcx.tcx.mk_ty_var(var)) }; let (a, b) = if self.a_is_expected { (a, b) } else { (b, a) }; - let (a, b) = match (a.kind(), b.kind()) { + let (ga, gb) = match (a.kind(), b.kind()) { (&ty::Opaque(..), _) => (a, generalize(b, true)?), (_, &ty::Opaque(..)) => (generalize(a, false)?, b), _ => unreachable!(), }; self.fields.obligations.extend( infcx - .handle_opaque_type(a, b, true, &self.fields.trace.cause, self.param_env())? + .handle_opaque_type(ga, gb, true, &self.fields.trace.cause, self.param_env()) + // Don't leak any generalized type variables out of this + // subtyping relation in the case of a type error. + .map_err(|err| { + let (ga, gb) = self.fields.infcx.resolve_vars_if_possible((ga, gb)); + if let TypeError::Sorts(sorts) = err && sorts.expected == ga && sorts.found == gb { + TypeError::Sorts(ExpectedFound { expected: a, found: b }) + } else { + err + } + })? .obligations, ); - Ok(a) + Ok(ga) } _ => { diff --git a/src/test/ui/impl-trait/issue-99914.rs b/src/test/ui/impl-trait/issue-99914.rs new file mode 100644 index 00000000000..4324a0229a6 --- /dev/null +++ b/src/test/ui/impl-trait/issue-99914.rs @@ -0,0 +1,13 @@ +// edition:2021 + +fn main() {} + +struct Error; +struct Okay; + +fn foo(t: Result) { + t.and_then(|t| -> _ { bar(t) }); + //~^ ERROR mismatched types +} + +async fn bar(t: Okay) {} diff --git a/src/test/ui/impl-trait/issue-99914.stderr b/src/test/ui/impl-trait/issue-99914.stderr new file mode 100644 index 00000000000..074d5d58d9a --- /dev/null +++ b/src/test/ui/impl-trait/issue-99914.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/issue-99914.rs:9:27 + | +LL | t.and_then(|t| -> _ { bar(t) }); + | ^^^^^^ expected enum `Result`, found opaque type + | +note: while checking the return type of the `async fn` + --> $DIR/issue-99914.rs:13:23 + | +LL | async fn bar(t: Okay) {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected enum `Result<_, Error>` + found opaque type `impl Future` +help: try wrapping the expression in `Ok` + | +LL | t.and_then(|t| -> _ { Ok(bar(t)) }); + | +++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`.