about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_trait_selection/src/opaque_types.rs17
-rw-r--r--src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs16
-rw-r--r--src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr15
3 files changed, 38 insertions, 10 deletions
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<A, B> = impl Into<&'static A>;
+//~^ ERROR the trait bound `&'static B: From<&A>` is not satisfied
+
+fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
+    (a, a)
+}
+
+fn main() {
+    println!("{}", <X<_, _> 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<A, B> = 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, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) where &'static B: From<&A> {
+   |                                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.