@@ -80,47 +80,69 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
8080 }
8181 if self . defining_use_anchor . is_some ( ) {
8282 let process = |a : Ty < ' tcx > , b : Ty < ' tcx > | match * a. kind ( ) {
83- ty:: Opaque ( def_id, substs) => Some ( self . register_hidden_type (
84- OpaqueTypeKey { def_id, substs } ,
85- cause. clone ( ) ,
86- param_env,
87- b,
88- // Check that this is `impl Trait` type is
89- // declared by `parent_def_id` -- i.e., one whose
90- // value we are inferring. At present, this is
91- // always true during the first phase of
92- // type-check, but not always true later on during
93- // NLL. Once we support named opaque types more fully,
94- // this same scenario will be able to arise during all phases.
95- //
96- // Here is an example using type alias `impl Trait`
97- // that indicates the distinction we are checking for:
98- //
99- // ```rust
100- // mod a {
101- // pub type Foo = impl Iterator;
102- // pub fn make_foo() -> Foo { .. }
103- // }
104- //
105- // mod b {
106- // fn foo() -> a::Foo { a::make_foo() }
107- // }
108- // ```
109- //
110- // Here, the return type of `foo` references an
111- // `Opaque` indeed, but not one whose value is
112- // presently being inferred. You can get into a
113- // similar situation with closure return types
114- // today:
115- //
116- // ```rust
117- // fn foo() -> impl Iterator { .. }
118- // fn bar() {
119- // let x = || foo(); // returns the Opaque assoc with `foo`
120- // }
121- // ```
122- self . opaque_type_origin ( def_id, cause. span ) ?,
123- ) ) ,
83+ ty:: Opaque ( def_id, substs) => {
84+ if let ty:: Opaque ( did2, _) = * b. kind ( ) {
85+ if self . opaque_type_origin ( did2, cause. span ) . is_some ( ) {
86+ self . tcx
87+ . sess
88+ . struct_span_err (
89+ cause. span ,
90+ "opaque type's hidden type cannot be another opaque type from the same scope" ,
91+ )
92+ . span_label ( cause. span , "one of the two opaque types used here has to be outside its defining scope" )
93+ . span_note (
94+ self . tcx . def_span ( def_id) ,
95+ "opaque type whose hidden type is being assigned" ,
96+ )
97+ . span_note (
98+ self . tcx . def_span ( did2) ,
99+ "opaque type being used as hidden type" ,
100+ )
101+ . emit ( ) ;
102+ }
103+ }
104+ Some ( self . register_hidden_type (
105+ OpaqueTypeKey { def_id, substs } ,
106+ cause. clone ( ) ,
107+ param_env,
108+ b,
109+ // Check that this is `impl Trait` type is
110+ // declared by `parent_def_id` -- i.e., one whose
111+ // value we are inferring. At present, this is
112+ // always true during the first phase of
113+ // type-check, but not always true later on during
114+ // NLL. Once we support named opaque types more fully,
115+ // this same scenario will be able to arise during all phases.
116+ //
117+ // Here is an example using type alias `impl Trait`
118+ // that indicates the distinction we are checking for:
119+ //
120+ // ```rust
121+ // mod a {
122+ // pub type Foo = impl Iterator;
123+ // pub fn make_foo() -> Foo { .. }
124+ // }
125+ //
126+ // mod b {
127+ // fn foo() -> a::Foo { a::make_foo() }
128+ // }
129+ // ```
130+ //
131+ // Here, the return type of `foo` references an
132+ // `Opaque` indeed, but not one whose value is
133+ // presently being inferred. You can get into a
134+ // similar situation with closure return types
135+ // today:
136+ //
137+ // ```rust
138+ // fn foo() -> impl Iterator { .. }
139+ // fn bar() {
140+ // let x = || foo(); // returns the Opaque assoc with `foo`
141+ // }
142+ // ```
143+ self . opaque_type_origin ( def_id, cause. span ) ?,
144+ ) )
145+ }
124146 _ => None ,
125147 } ;
126148 if let Some ( res) = process ( a, b) {
0 commit comments