Skip to content

Commit 2b862be

Browse files
committed
Auto merge of #89024 - oli-obk:lazy_tait_is_not_limited_to_being_used_in_return_position, r=nikomatsakis
Lazy TAIT preparation cleanups Check that TAIT generics are fully generic in mir typeck instead of wf-check, as wf-check can by definition only check TAIT in return position and not account for TAITs defined in the body of the function r? `@spastorino` `@nikomatsakis`
2 parents bf64232 + 6067ead commit 2b862be

33 files changed

+433
-272
lines changed

Diff for: compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+106-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
use rustc_data_structures::fx::FxHashMap;
12
use rustc_data_structures::vec_map::VecMap;
3+
use rustc_hir::OpaqueTyOrigin;
4+
use rustc_infer::infer::opaque_types::OpaqueTypeDecl;
25
use rustc_infer::infer::InferCtxt;
6+
use rustc_middle::ty::subst::GenericArgKind;
37
use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
48
use rustc_span::Span;
59
use rustc_trait_selection::opaque_types::InferCtxtExt;
@@ -50,13 +54,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
5054
pub(crate) fn infer_opaque_types(
5155
&self,
5256
infcx: &InferCtxt<'_, 'tcx>,
53-
opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
57+
opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>,
5458
span: Span,
5559
) -> VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>> {
5660
opaque_ty_decls
5761
.into_iter()
58-
.map(|(opaque_type_key, concrete_type)| {
62+
.filter_map(|(opaque_type_key, decl)| {
5963
let substs = opaque_type_key.substs;
64+
let concrete_type = decl.concrete_ty;
6065
debug!(?concrete_type, ?substs);
6166

6267
let mut subst_regions = vec![self.universal_regions.fr_static];
@@ -94,7 +99,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
9499
universal_concrete_type,
95100
span,
96101
);
97-
(opaque_type_key, remapped_type)
102+
103+
check_opaque_type_parameter_valid(
104+
infcx.tcx,
105+
opaque_type_key,
106+
OpaqueTypeDecl { concrete_ty: remapped_type, ..decl },
107+
)
108+
.then_some((opaque_type_key, remapped_type))
98109
})
99110
.collect()
100111
}
@@ -119,3 +130,95 @@ impl<'tcx> RegionInferenceContext<'tcx> {
119130
})
120131
}
121132
}
133+
134+
fn check_opaque_type_parameter_valid(
135+
tcx: TyCtxt<'_>,
136+
opaque_type_key: OpaqueTypeKey<'_>,
137+
decl: OpaqueTypeDecl<'_>,
138+
) -> bool {
139+
match decl.origin {
140+
// No need to check return position impl trait (RPIT)
141+
// because for type and const parameters they are correct
142+
// by construction: we convert
143+
//
144+
// fn foo<P0..Pn>() -> impl Trait
145+
//
146+
// into
147+
//
148+
// type Foo<P0...Pn>
149+
// fn foo<P0..Pn>() -> Foo<P0...Pn>.
150+
//
151+
// For lifetime parameters we convert
152+
//
153+
// fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
154+
//
155+
// into
156+
//
157+
// type foo::<'p0..'pn>::Foo<'q0..'qm>
158+
// fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
159+
//
160+
// which would error here on all of the `'static` args.
161+
OpaqueTyOrigin::FnReturn | OpaqueTyOrigin::AsyncFn => return true,
162+
// Check these
163+
OpaqueTyOrigin::TyAlias => {}
164+
}
165+
let span = decl.definition_span;
166+
let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
167+
let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
168+
for (i, arg) in opaque_type_key.substs.iter().enumerate() {
169+
let arg_is_param = match arg.unpack() {
170+
GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
171+
GenericArgKind::Lifetime(ty::ReStatic) => {
172+
tcx.sess
173+
.struct_span_err(span, "non-defining opaque type use in defining scope")
174+
.span_label(
175+
tcx.def_span(opaque_generics.param_at(i, tcx).def_id),
176+
"cannot use static lifetime; use a bound lifetime \
177+
instead or remove the lifetime parameter from the \
178+
opaque type",
179+
)
180+
.emit();
181+
return false;
182+
}
183+
GenericArgKind::Lifetime(lt) => {
184+
matches!(lt, ty::ReEarlyBound(_) | ty::ReFree(_))
185+
}
186+
GenericArgKind::Const(ct) => matches!(ct.val, ty::ConstKind::Param(_)),
187+
};
188+
189+
if arg_is_param {
190+
seen_params.entry(arg).or_default().push(i);
191+
} else {
192+
// Prevent `fn foo() -> Foo<u32>` from being defining.
193+
let opaque_param = opaque_generics.param_at(i, tcx);
194+
tcx.sess
195+
.struct_span_err(span, "non-defining opaque type use in defining scope")
196+
.span_note(
197+
tcx.def_span(opaque_param.def_id),
198+
&format!(
199+
"used non-generic {} `{}` for generic parameter",
200+
opaque_param.kind.descr(),
201+
arg,
202+
),
203+
)
204+
.emit();
205+
return false;
206+
}
207+
}
208+
209+
for (_, indices) in seen_params {
210+
if indices.len() > 1 {
211+
let descr = opaque_generics.param_at(indices[0], tcx).kind.descr();
212+
let spans: Vec<_> = indices
213+
.into_iter()
214+
.map(|i| tcx.def_span(opaque_generics.param_at(i, tcx).def_id))
215+
.collect();
216+
tcx.sess
217+
.struct_span_err(span, "non-defining opaque type use in defining scope")
218+
.span_note(spans, &format!("{} used multiple times", descr))
219+
.emit();
220+
return false;
221+
}
222+
}
223+
true
224+
}

Diff for: compiler/rustc_borrowck/src/type_check/mod.rs

+10-8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use rustc_hir::def_id::LocalDefId;
1414
use rustc_hir::lang_items::LangItem;
1515
use rustc_index::vec::{Idx, IndexVec};
1616
use rustc_infer::infer::canonical::QueryRegionConstraints;
17+
use rustc_infer::infer::opaque_types::OpaqueTypeDecl;
1718
use rustc_infer::infer::outlives::env::RegionBoundPairs;
1819
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
1920
use rustc_infer::infer::{
@@ -193,16 +194,17 @@ pub(crate) fn type_check<'mir, 'tcx>(
193194

194195
opaque_type_values
195196
.into_iter()
196-
.filter_map(|(opaque_type_key, decl)| {
197-
let mut revealed_ty = infcx.resolve_vars_if_possible(decl.concrete_ty);
198-
if revealed_ty.has_infer_types_or_consts() {
197+
.filter_map(|(opaque_type_key, mut decl)| {
198+
decl.concrete_ty = infcx.resolve_vars_if_possible(decl.concrete_ty);
199+
if decl.concrete_ty.has_infer_types_or_consts() {
199200
infcx.tcx.sess.delay_span_bug(
200201
body.span,
201-
&format!("could not resolve {:#?}", revealed_ty.kind()),
202+
&format!("could not resolve {:#?}", decl.concrete_ty.kind()),
202203
);
203-
revealed_ty = infcx.tcx.ty_error();
204+
decl.concrete_ty = infcx.tcx.ty_error();
204205
}
205-
let concrete_is_opaque = if let ty::Opaque(def_id, _) = revealed_ty.kind() {
206+
let concrete_is_opaque = if let ty::Opaque(def_id, _) = decl.concrete_ty.kind()
207+
{
206208
*def_id == opaque_type_key.def_id
207209
} else {
208210
false
@@ -234,7 +236,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
234236
);
235237
None
236238
} else {
237-
Some((opaque_type_key, revealed_ty))
239+
Some((opaque_type_key, decl))
238240
}
239241
})
240242
.collect()
@@ -890,7 +892,7 @@ struct BorrowCheckContext<'a, 'tcx> {
890892
crate struct MirTypeckResults<'tcx> {
891893
crate constraints: MirTypeckRegionConstraints<'tcx>,
892894
crate universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
893-
crate opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
895+
crate opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>,
894896
}
895897

896898
/// A collection of region constraints that must be satisfied for the

Diff for: compiler/rustc_trait_selection/src/opaque_types.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -1062,11 +1062,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
10621062
/// Here, `def_id` is the `LocalDefId` of the defining use of the opaque type (e.g., `f1` or `f2`),
10631063
/// and `opaque_hir_id` is the `HirId` of the definition of the opaque type `Baz`.
10641064
/// For the above example, this function returns `true` for `f1` and `false` for `f2`.
1065-
pub fn may_define_opaque_type(
1066-
tcx: TyCtxt<'_>,
1067-
def_id: LocalDefId,
1068-
opaque_hir_id: hir::HirId,
1069-
) -> bool {
1065+
fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hir::HirId) -> bool {
10701066
let mut hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
10711067

10721068
// Named opaque types can be defined by any siblings or children of siblings.

0 commit comments

Comments
 (0)