From 9e547b446433d63e3fe99bacfdaedf97fed31a8a Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Jun 2021 18:12:43 -0300 Subject: [PATCH] Differentiate different defining uses of taits when they reference distinct generic parameters --- .../rustc_trait_selection/src/opaque_types.rs | 17 +++++++---------- .../multiple-def-uses-in-one-fn.rs | 16 ++++++++++++++++ .../multiple-def-uses-in-one-fn.stderr | 15 +++++++++++++++ 3 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs create mode 100644 src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 8b864d67536..89ec211f262 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -11,7 +11,7 @@ use rustc_infer::infer::free_regions::FreeRegionRelations; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{self, InferCtxt, InferOk}; use rustc_middle::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor}; -use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef}; +use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst}; use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt}; use rustc_span::Span; @@ -1007,7 +1007,9 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { ), }; if in_definition_scope { - return self.fold_opaque_ty(ty, def_id.to_def_id(), substs, origin); + let opaque_type_key = + OpaqueTypeKey { def_id: def_id.to_def_id(), substs }; + return self.fold_opaque_ty(ty, opaque_type_key, origin); } debug!( @@ -1029,23 +1031,18 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { fn fold_opaque_ty( &mut self, ty: Ty<'tcx>, - def_id: DefId, - substs: SubstsRef<'tcx>, + opaque_type_key: OpaqueTypeKey<'tcx>, origin: hir::OpaqueTyOrigin, ) -> Ty<'tcx> { let infcx = self.infcx; let tcx = infcx.tcx; + let OpaqueTypeKey { def_id, substs } = opaque_type_key; debug!("instantiate_opaque_types: Opaque(def_id={:?}, substs={:?})", def_id, substs); // Use the same type variable if the exact same opaque type appears more // than once in the return type (e.g., if it's passed to a type alias). - if let Some(opaque_defn) = self - .opaque_types - .iter() - .find(|(opaque_type_key, _)| opaque_type_key.def_id == def_id) - .map(|(_, opaque_defn)| opaque_defn) - { + if let Some(opaque_defn) = self.opaque_types.get(&opaque_type_key) { debug!("instantiate_opaque_types: returning concrete ty {:?}", opaque_defn.concrete_ty); return opaque_defn.concrete_ty; } diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs new file mode 100644 index 00000000000..67351e20159 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs @@ -0,0 +1,16 @@ +// https://github.com/rust-lang/rust/issues/73481 +// This test used to cause unsoundness, since one of the two possible +// resolutions was chosen at random instead of erroring due to conflicts. + +#![feature(min_type_alias_impl_trait)] + +type X = impl Into<&'static A>; +//~^ ERROR the trait bound `&'static B: From<&A>` is not satisfied + +fn f(a: &'static A, b: B) -> (X, X) { + (a, a) +} + +fn main() { + println!("{}", as Into<&String>>::into(f(&[1isize, 2, 3], String::new()).1)); +} diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr new file mode 100644 index 00000000000..731c6e2788d --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `&'static B: From<&A>` is not satisfied + --> $DIR/multiple-def-uses-in-one-fn.rs:7:16 + | +LL | type X = impl Into<&'static A>; + | ^^^^^^^^^^^^^^^^^^^^^ the trait `From<&A>` is not implemented for `&'static B` + | + = note: required because of the requirements on the impl of `Into<&'static B>` for `&A` +help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement + | +LL | fn f(a: &'static A, b: B) -> (X, X) where &'static B: From<&A> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`.