Skip to content

Commit 51a6550

Browse files
committed
Document some opaque types code
1 parent ea998cb commit 51a6550

File tree

4 files changed

+109
-100
lines changed

4 files changed

+109
-100
lines changed

src/librustc_resolve/late/lifetimes.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,8 @@ enum Elide {
258258
Exact(Region),
259259
/// Less or more than one lifetime were found, error on unspecified.
260260
Error(Vec<ElisionFailureInfo>),
261-
/// Forbid lifetime elision inside of a larger scope that does. For
262-
/// example, in let position impl trait.
261+
/// Forbid lifetime elision inside of a larger scope where it would be
262+
/// permitted. For example, in let position impl trait.
263263
Forbid,
264264
}
265265

src/librustc_trait_selection/opaque_types.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -407,12 +407,20 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
407407

408408
let first_own_region = match opaque_defn.origin {
409409
hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => {
410-
// For these opaque types, only the item's own lifetime
411-
// parameters are considered.
410+
// We lower
411+
//
412+
// fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
413+
//
414+
// into
415+
//
416+
// type foo::<'p0..'pn>::Foo<'q0..'qm>
417+
// fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
418+
//
419+
// For these types we onlt iterate over `'l0..lm` below.
412420
tcx.generics_of(def_id).parent_count
413421
}
414422
// These opaque type inherit all lifetime parameters from their
415-
// parent.
423+
// parent, so we have to check them all.
416424
hir::OpaqueTyOrigin::Binding | hir::OpaqueTyOrigin::Misc => 0,
417425
};
418426

src/librustc_typeck/check/wfcheck.rs

+86-95
Original file line numberDiff line numberDiff line change
@@ -801,18 +801,14 @@ fn check_where_clauses<'tcx, 'fcx>(
801801
traits::Obligation::new(cause, fcx.param_env, pred)
802802
});
803803

804-
let mut predicates = predicates.instantiate_identity(fcx.tcx);
804+
let predicates = predicates.instantiate_identity(fcx.tcx);
805805

806806
if let Some((mut return_ty, span)) = return_ty {
807807
if return_ty.has_infer_types_or_consts() {
808808
fcx.select_obligations_where_possible(false, |_| {});
809809
return_ty = fcx.resolve_vars_if_possible(&return_ty);
810810
}
811-
let opaque_types = check_opaque_types(tcx, fcx, def_id.expect_local(), span, return_ty);
812-
for _ in 0..opaque_types.len() {
813-
predicates.spans.push(span);
814-
}
815-
predicates.predicates.extend(opaque_types);
811+
check_opaque_types(tcx, fcx, def_id.expect_local(), span, return_ty);
816812
}
817813

818814
let predicates = fcx.normalize_associated_types_in(span, &predicates);
@@ -884,113 +880,109 @@ fn check_opaque_types<'fcx, 'tcx>(
884880
fn_def_id: LocalDefId,
885881
span: Span,
886882
ty: Ty<'tcx>,
887-
) -> Vec<ty::Predicate<'tcx>> {
883+
) {
888884
trace!("check_opaque_types(ty={:?})", ty);
889-
let mut substituted_predicates = Vec::new();
890885
ty.fold_with(&mut ty::fold::BottomUpFolder {
891886
tcx: fcx.tcx,
892887
ty_op: |ty| {
893888
if let ty::Opaque(def_id, substs) = ty.kind {
894889
trace!("check_opaque_types: opaque_ty, {:?}, {:?}", def_id, substs);
895890
let generics = tcx.generics_of(def_id);
896-
// Only check named `impl Trait` types defined in this crate.
897-
if !def_id.is_local() {
891+
892+
let opaque_hir_id = if let Some(local_id) = def_id.as_local() {
893+
tcx.hir().as_local_hir_id(local_id)
894+
} else {
895+
// Opaque types from other crates won't have defining uses in this crate.
898896
return ty;
899-
}
900-
let opaque_hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
897+
};
901898
if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: Some(_), .. }) =
902899
tcx.hir().expect_item(opaque_hir_id).kind
903900
{
904-
// Don't check return position impl trait.
901+
// No need to check return position impl trait (RPIT)
902+
// because for type and const parameters they are correct
903+
// by construction: we convert
904+
//
905+
// fn foo<P0..Pn>() -> impl Trait
906+
//
907+
// into
908+
//
909+
// type Foo<P0...Pn>
910+
// fn foo<P0..Pn>() -> Foo<P0...Pn>.
911+
//
912+
// For lifetime parameters we convert
913+
//
914+
// fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
915+
//
916+
// into
917+
//
918+
// type foo::<'p0..'pn>::Foo<'q0..'qm>
919+
// fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
920+
//
921+
// which would error here on all of the `'static` args.
922+
return ty;
923+
}
924+
if !may_define_opaque_type(tcx, fn_def_id, opaque_hir_id) {
905925
return ty;
906926
}
907-
if may_define_opaque_type(tcx, fn_def_id, opaque_hir_id) {
908-
trace!("check_opaque_types: may define, generics={:#?}", generics);
909-
let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
910-
for (i, arg) in substs.iter().enumerate() {
911-
let arg_is_param = match arg.unpack() {
912-
GenericArgKind::Type(ty) => matches!(ty.kind, ty::Param(_)),
913-
914-
GenericArgKind::Lifetime(region) => {
915-
if let ty::ReStatic = region {
916-
tcx.sess
917-
.struct_span_err(
918-
span,
919-
"non-defining opaque type use in defining scope",
920-
)
921-
.span_label(
922-
tcx.def_span(generics.param_at(i, tcx).def_id),
923-
"cannot use static lifetime; use a bound lifetime \
927+
trace!("check_opaque_types: may define, generics={:#?}", generics);
928+
let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
929+
for (i, arg) in substs.iter().enumerate() {
930+
let arg_is_param = match arg.unpack() {
931+
GenericArgKind::Type(ty) => matches!(ty.kind, ty::Param(_)),
932+
933+
GenericArgKind::Lifetime(region) => {
934+
if let ty::ReStatic = region {
935+
tcx.sess
936+
.struct_span_err(
937+
span,
938+
"non-defining opaque type use in defining scope",
939+
)
940+
.span_label(
941+
tcx.def_span(generics.param_at(i, tcx).def_id),
942+
"cannot use static lifetime; use a bound lifetime \
924943
instead or remove the lifetime parameter from the \
925944
opaque type",
926-
)
927-
.emit();
928-
continue;
929-
}
930-
931-
true
945+
)
946+
.emit();
947+
continue;
932948
}
933949

934-
GenericArgKind::Const(ct) => matches!(ct.val, ty::ConstKind::Param(_)),
935-
};
936-
937-
if arg_is_param {
938-
seen_params.entry(arg).or_default().push(i);
939-
} else {
940-
// Prevent `fn foo() -> Foo<u32>` from being defining.
941-
let opaque_param = generics.param_at(i, tcx);
942-
tcx.sess
943-
.struct_span_err(
944-
span,
945-
"non-defining opaque type use in defining scope",
946-
)
947-
.span_note(
948-
tcx.def_span(opaque_param.def_id),
949-
&format!(
950-
"used non-generic {} `{}` for generic parameter",
951-
opaque_param.kind.descr(),
952-
arg,
953-
),
954-
)
955-
.emit();
956-
}
957-
} // for (arg, param)
958-
959-
for (_, indices) in seen_params {
960-
if indices.len() > 1 {
961-
let descr = generics.param_at(indices[0], tcx).kind.descr();
962-
let spans: Vec<_> = indices
963-
.into_iter()
964-
.map(|i| tcx.def_span(generics.param_at(i, tcx).def_id))
965-
.collect();
966-
tcx.sess
967-
.struct_span_err(
968-
span,
969-
"non-defining opaque type use in defining scope",
970-
)
971-
.span_note(spans, &format!("{} used multiple times", descr))
972-
.emit();
950+
true
973951
}
952+
953+
GenericArgKind::Const(ct) => matches!(ct.val, ty::ConstKind::Param(_)),
954+
};
955+
956+
if arg_is_param {
957+
seen_params.entry(arg).or_default().push(i);
958+
} else {
959+
// Prevent `fn foo() -> Foo<u32>` from being defining.
960+
let opaque_param = generics.param_at(i, tcx);
961+
tcx.sess
962+
.struct_span_err(span, "non-defining opaque type use in defining scope")
963+
.span_note(
964+
tcx.def_span(opaque_param.def_id),
965+
&format!(
966+
"used non-generic {} `{}` for generic parameter",
967+
opaque_param.kind.descr(),
968+
arg,
969+
),
970+
)
971+
.emit();
974972
}
975-
} // if may_define_opaque_type
976-
977-
// Now register the bounds on the parameters of the opaque type
978-
// so the parameters given by the function need to fulfill them.
979-
//
980-
// type Foo<T: Bar> = impl Baz + 'static;
981-
// fn foo<U>() -> Foo<U> { .. *}
982-
//
983-
// becomes
984-
//
985-
// type Foo<T: Bar> = impl Baz + 'static;
986-
// fn foo<U: Bar>() -> Foo<U> { .. *}
987-
let predicates = tcx.predicates_of(def_id);
988-
trace!("check_opaque_types: may define, predicates={:#?}", predicates,);
989-
for &(pred, _) in predicates.predicates {
990-
let substituted_pred = pred.subst(fcx.tcx, substs);
991-
// Avoid duplication of predicates that contain no parameters, for example.
992-
if !predicates.predicates.iter().any(|&(p, _)| p == substituted_pred) {
993-
substituted_predicates.push(substituted_pred);
973+
} // for (arg, param)
974+
975+
for (_, indices) in seen_params {
976+
if indices.len() > 1 {
977+
let descr = generics.param_at(indices[0], tcx).kind.descr();
978+
let spans: Vec<_> = indices
979+
.into_iter()
980+
.map(|i| tcx.def_span(generics.param_at(i, tcx).def_id))
981+
.collect();
982+
tcx.sess
983+
.struct_span_err(span, "non-defining opaque type use in defining scope")
984+
.span_note(spans, &format!("{} used multiple times", descr))
985+
.emit();
994986
}
995987
}
996988
} // if let Opaque
@@ -999,7 +991,6 @@ fn check_opaque_types<'fcx, 'tcx>(
999991
lt_op: |lt| lt,
1000992
ct_op: |ct| ct,
1001993
});
1002-
substituted_predicates
1003994
}
1004995

1005996
const HELP_FOR_SELF_TYPE: &str = "consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, \

src/librustc_typeck/collect/type_of.rs

+10
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,16 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
573573
}
574574
}
575575

576+
/// Retrieve the inferred concrete type for let position impl trait.
577+
///
578+
/// This is different to other kinds of impl trait because:
579+
///
580+
/// 1. We know which function contains the defining use (the function that
581+
/// contains the let statement)
582+
/// 2. We do not currently allow (free) lifetimes in the return type. `let`
583+
/// statements in some statically unreachable code are removed from the MIR
584+
/// by the time we borrow check, and it's not clear how we should handle
585+
/// those.
576586
fn let_position_impl_trait_type(tcx: TyCtxt<'_>, opaque_ty_id: LocalDefId) -> Ty<'_> {
577587
let scope = tcx.hir().get_defining_scope(tcx.hir().as_local_hir_id(opaque_ty_id));
578588
let scope_def_id = tcx.hir().local_def_id(scope);

0 commit comments

Comments
 (0)