Skip to content

Commit 7a4ac84

Browse files
committed
For non-defining opaque type usage errors, don't try to also prove all trait bounds
1 parent 253408b commit 7a4ac84

10 files changed

+108
-290
lines changed

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+1-106
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
use rustc_data_structures::fx::FxHashMap;
21
use rustc_data_structures::vec_map::VecMap;
32
use rustc_hir::def_id::DefId;
43
use rustc_hir::OpaqueTyOrigin;
54
use rustc_infer::infer::InferCtxt;
6-
use rustc_middle::ty::subst::GenericArgKind;
75
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, TyCtxt, TypeFoldable};
8-
use rustc_span::Span;
96
use rustc_trait_selection::opaque_types::InferCtxtExt;
107

118
use super::RegionInferenceContext;
@@ -107,21 +104,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
107104

108105
let opaque_type_key =
109106
OpaqueTypeKey { def_id: opaque_type_key.def_id, substs: universal_substs };
110-
let remapped_type = infcx.infer_opaque_definition_from_instantiation(
107+
let ty = infcx.infer_opaque_definition_from_instantiation(
111108
opaque_type_key,
112109
universal_concrete_type,
113110
origin,
114111
);
115-
let ty = if check_opaque_type_parameter_valid(
116-
infcx.tcx,
117-
opaque_type_key,
118-
origin,
119-
concrete_type.span,
120-
) {
121-
remapped_type
122-
} else {
123-
infcx.tcx.ty_error()
124-
};
125112
// Sometimes two opaque types are the same only after we remap the generic parameters
126113
// back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to `(X, Y)`
127114
// and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we only know that
@@ -184,95 +171,3 @@ impl<'tcx> RegionInferenceContext<'tcx> {
184171
})
185172
}
186173
}
187-
188-
fn check_opaque_type_parameter_valid(
189-
tcx: TyCtxt<'_>,
190-
opaque_type_key: OpaqueTypeKey<'_>,
191-
origin: OpaqueTyOrigin,
192-
span: Span,
193-
) -> bool {
194-
match origin {
195-
// No need to check return position impl trait (RPIT)
196-
// because for type and const parameters they are correct
197-
// by construction: we convert
198-
//
199-
// fn foo<P0..Pn>() -> impl Trait
200-
//
201-
// into
202-
//
203-
// type Foo<P0...Pn>
204-
// fn foo<P0..Pn>() -> Foo<P0...Pn>.
205-
//
206-
// For lifetime parameters we convert
207-
//
208-
// fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
209-
//
210-
// into
211-
//
212-
// type foo::<'p0..'pn>::Foo<'q0..'qm>
213-
// fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
214-
//
215-
// which would error here on all of the `'static` args.
216-
OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return true,
217-
// Check these
218-
OpaqueTyOrigin::TyAlias => {}
219-
}
220-
let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
221-
let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
222-
for (i, arg) in opaque_type_key.substs.iter().enumerate() {
223-
let arg_is_param = match arg.unpack() {
224-
GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
225-
GenericArgKind::Lifetime(lt) if lt.is_static() => {
226-
tcx.sess
227-
.struct_span_err(span, "non-defining opaque type use in defining scope")
228-
.span_label(
229-
tcx.def_span(opaque_generics.param_at(i, tcx).def_id),
230-
"cannot use static lifetime; use a bound lifetime \
231-
instead or remove the lifetime parameter from the \
232-
opaque type",
233-
)
234-
.emit();
235-
return false;
236-
}
237-
GenericArgKind::Lifetime(lt) => {
238-
matches!(*lt, ty::ReEarlyBound(_) | ty::ReFree(_))
239-
}
240-
GenericArgKind::Const(ct) => matches!(ct.val(), ty::ConstKind::Param(_)),
241-
};
242-
243-
if arg_is_param {
244-
seen_params.entry(arg).or_default().push(i);
245-
} else {
246-
// Prevent `fn foo() -> Foo<u32>` from being defining.
247-
let opaque_param = opaque_generics.param_at(i, tcx);
248-
tcx.sess
249-
.struct_span_err(span, "non-defining opaque type use in defining scope")
250-
.span_note(
251-
tcx.def_span(opaque_param.def_id),
252-
&format!(
253-
"used non-generic {} `{}` for generic parameter",
254-
opaque_param.kind.descr(),
255-
arg,
256-
),
257-
)
258-
.emit();
259-
return false;
260-
}
261-
}
262-
263-
for (_, indices) in seen_params {
264-
if indices.len() > 1 {
265-
let descr = opaque_generics.param_at(indices[0], tcx).kind.descr();
266-
let spans: Vec<_> = indices
267-
.into_iter()
268-
.map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id))
269-
.collect();
270-
tcx.sess
271-
.struct_span_err(span, "non-defining opaque type use in defining scope")
272-
.span_note(spans, &format!("{} used multiple times", descr))
273-
.emit();
274-
return false;
275-
}
276-
}
277-
true
278-
}

compiler/rustc_trait_selection/src/opaque_types.rs

+101
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
8282
));
8383
debug!(?definition_ty);
8484

85+
if !check_opaque_type_parameter_valid(
86+
self.tcx,
87+
opaque_type_key,
88+
origin,
89+
instantiated_ty.span,
90+
) {
91+
return self.tcx.ty_error();
92+
}
93+
8594
// Only check this for TAIT. RPIT already supports `src/test/ui/impl-trait/nested-return-type2.rs`
8695
// on stable and we'd break that.
8796
if let OpaqueTyOrigin::TyAlias = origin {
@@ -148,6 +157,98 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
148157
}
149158
}
150159

160+
fn check_opaque_type_parameter_valid(
161+
tcx: TyCtxt<'_>,
162+
opaque_type_key: OpaqueTypeKey<'_>,
163+
origin: OpaqueTyOrigin,
164+
span: Span,
165+
) -> bool {
166+
match origin {
167+
// No need to check return position impl trait (RPIT)
168+
// because for type and const parameters they are correct
169+
// by construction: we convert
170+
//
171+
// fn foo<P0..Pn>() -> impl Trait
172+
//
173+
// into
174+
//
175+
// type Foo<P0...Pn>
176+
// fn foo<P0..Pn>() -> Foo<P0...Pn>.
177+
//
178+
// For lifetime parameters we convert
179+
//
180+
// fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
181+
//
182+
// into
183+
//
184+
// type foo::<'p0..'pn>::Foo<'q0..'qm>
185+
// fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
186+
//
187+
// which would error here on all of the `'static` args.
188+
OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return true,
189+
// Check these
190+
OpaqueTyOrigin::TyAlias => {}
191+
}
192+
let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
193+
let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
194+
for (i, arg) in opaque_type_key.substs.iter().enumerate() {
195+
let arg_is_param = match arg.unpack() {
196+
GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
197+
GenericArgKind::Lifetime(lt) if lt.is_static() => {
198+
tcx.sess
199+
.struct_span_err(span, "non-defining opaque type use in defining scope")
200+
.span_label(
201+
tcx.def_span(opaque_generics.param_at(i, tcx).def_id),
202+
"cannot use static lifetime; use a bound lifetime \
203+
instead or remove the lifetime parameter from the \
204+
opaque type",
205+
)
206+
.emit();
207+
return false;
208+
}
209+
GenericArgKind::Lifetime(lt) => {
210+
matches!(*lt, ty::ReEarlyBound(_) | ty::ReFree(_))
211+
}
212+
GenericArgKind::Const(ct) => matches!(ct.val(), ty::ConstKind::Param(_)),
213+
};
214+
215+
if arg_is_param {
216+
seen_params.entry(arg).or_default().push(i);
217+
} else {
218+
// Prevent `fn foo() -> Foo<u32>` from being defining.
219+
let opaque_param = opaque_generics.param_at(i, tcx);
220+
tcx.sess
221+
.struct_span_err(span, "non-defining opaque type use in defining scope")
222+
.span_note(
223+
tcx.def_span(opaque_param.def_id),
224+
&format!(
225+
"used non-generic {} `{}` for generic parameter",
226+
opaque_param.kind.descr(),
227+
arg,
228+
),
229+
)
230+
.emit();
231+
return false;
232+
}
233+
}
234+
235+
for (_, indices) in seen_params {
236+
if indices.len() > 1 {
237+
let descr = opaque_generics.param_at(indices[0], tcx).kind.descr();
238+
let spans: Vec<_> = indices
239+
.into_iter()
240+
.map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id))
241+
.collect();
242+
tcx.sess
243+
.struct_span_err(span, "non-defining opaque type use in defining scope")
244+
.span_note(spans, &format!("{} used multiple times", descr))
245+
.emit();
246+
return false;
247+
}
248+
}
249+
true
250+
}
251+
151252
struct ReverseMapper<'tcx> {
152253
tcx: TyCtxt<'tcx>,
153254

src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs

-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ type TwoConsts<const X: usize, const Y: usize> = impl Debug;
1515
fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
1616
t
1717
//~^ ERROR non-defining opaque type use in defining scope
18-
//~| ERROR `U` doesn't implement `Debug`
1918
}
2019

2120
fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> {
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,3 @@
1-
error[E0277]: `U` doesn't implement `Debug`
2-
--> $DIR/generic_duplicate_param_use.rs:16:5
3-
|
4-
LL | t
5-
| ^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
6-
|
7-
help: consider restricting type parameter `U`
8-
|
9-
LL | type TwoTys<T, U: std::fmt::Debug> = impl Debug;
10-
| +++++++++++++++++
11-
121
error: non-defining opaque type use in defining scope
132
--> $DIR/generic_duplicate_param_use.rs:16:5
143
|
@@ -22,7 +11,7 @@ LL | type TwoTys<T, U> = impl Debug;
2211
| ^ ^
2312

2413
error: non-defining opaque type use in defining scope
25-
--> $DIR/generic_duplicate_param_use.rs:22:5
14+
--> $DIR/generic_duplicate_param_use.rs:21:5
2615
|
2716
LL | t
2817
| ^
@@ -34,7 +23,7 @@ LL | type TwoLifetimes<'a, 'b> = impl Debug;
3423
| ^^ ^^
3524

3625
error: non-defining opaque type use in defining scope
37-
--> $DIR/generic_duplicate_param_use.rs:27:5
26+
--> $DIR/generic_duplicate_param_use.rs:26:5
3827
|
3928
LL | t
4029
| ^
@@ -45,6 +34,5 @@ note: constant used multiple times
4534
LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug;
4635
| ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
4736

48-
error: aborting due to 4 previous errors
37+
error: aborting due to 3 previous errors
4938

50-
For more information about this error, try `rustc --explain E0277`.

src/test/ui/type-alias-impl-trait/issue-60564.rs

-8
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,6 @@ where
1919
fn iter_bits(self, n: u8) -> Self::BitsIter {
2020
(0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
2121
//~^ ERROR non-defining opaque type use in defining scope
22-
//~| ERROR type mismatch resolving
23-
//~| ERROR type mismatch resolving `<T as TryInto<u8>>::Error == E`
24-
//~| ERROR no implementation for `T >> T`
25-
//~| ERROR no implementation for `T & T`
26-
//~| ERROR the trait bound `T: From<u8>`
27-
//~| ERROR the trait bound `T: Copy` is not satisfied
28-
//~| ERROR `E` doesn't implement `Debug`
29-
//~| ERROR the trait bound `u8: From<T>` is not satisfied
3022
}
3123
}
3224

0 commit comments

Comments
 (0)