Skip to content

Commit c4926d0

Browse files
committed
Auto merge of rust-lang#78725 - sexxi-goose:fix-78720, r=nikomatsakis
Remove extra call to upvar_tys We already visit the tuple of upvar_tys, we don't need to visit each individual type. Fixes rust-lang#78720 r? `@ghost`
2 parents 29c4358 + e35e46c commit c4926d0

File tree

5 files changed

+205
-115
lines changed

5 files changed

+205
-115
lines changed

compiler/rustc_middle/src/ty/layout.rs

+129-99
Original file line numberDiff line numberDiff line change
@@ -2105,118 +2105,148 @@ where
21052105
}
21062106

21072107
fn field(this: TyAndLayout<'tcx>, cx: &C, i: usize) -> C::TyAndLayout {
2108-
let tcx = cx.tcx();
2109-
let tag_layout = |tag: &Scalar| -> C::TyAndLayout {
2110-
let layout = Layout::scalar(cx, tag.clone());
2111-
MaybeResult::from(Ok(TyAndLayout {
2112-
layout: tcx.intern_layout(layout),
2113-
ty: tag.value.to_ty(tcx),
2114-
}))
2115-
};
2108+
enum TyMaybeWithLayout<C: LayoutOf> {
2109+
Ty(C::Ty),
2110+
TyAndLayout(C::TyAndLayout),
2111+
}
21162112

2117-
cx.layout_of(match *this.ty.kind() {
2118-
ty::Bool
2119-
| ty::Char
2120-
| ty::Int(_)
2121-
| ty::Uint(_)
2122-
| ty::Float(_)
2123-
| ty::FnPtr(_)
2124-
| ty::Never
2125-
| ty::FnDef(..)
2126-
| ty::GeneratorWitness(..)
2127-
| ty::Foreign(..)
2128-
| ty::Dynamic(..) => bug!("TyAndLayout::field_type({:?}): not applicable", this),
2129-
2130-
// Potentially-fat pointers.
2131-
ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
2132-
assert!(i < this.fields.count());
2133-
2134-
// Reuse the fat `*T` type as its own thin pointer data field.
2135-
// This provides information about, e.g., DST struct pointees
2136-
// (which may have no non-DST form), and will work as long
2137-
// as the `Abi` or `FieldsShape` is checked by users.
2138-
if i == 0 {
2139-
let nil = tcx.mk_unit();
2140-
let ptr_ty = if this.ty.is_unsafe_ptr() {
2141-
tcx.mk_mut_ptr(nil)
2142-
} else {
2143-
tcx.mk_mut_ref(tcx.lifetimes.re_static, nil)
2144-
};
2145-
return MaybeResult::from(cx.layout_of(ptr_ty).to_result().map(
2146-
|mut ptr_layout| {
2147-
ptr_layout.ty = this.ty;
2148-
ptr_layout
2149-
},
2150-
));
2151-
}
2113+
fn ty_and_layout_kind<
2114+
C: LayoutOf<Ty = Ty<'tcx>, TyAndLayout: MaybeResult<TyAndLayout<'tcx>>>
2115+
+ HasTyCtxt<'tcx>
2116+
+ HasParamEnv<'tcx>,
2117+
>(
2118+
this: TyAndLayout<'tcx>,
2119+
cx: &C,
2120+
i: usize,
2121+
ty: C::Ty,
2122+
) -> TyMaybeWithLayout<C> {
2123+
let tcx = cx.tcx();
2124+
let tag_layout = |tag: &Scalar| -> C::TyAndLayout {
2125+
let layout = Layout::scalar(cx, tag.clone());
2126+
MaybeResult::from(Ok(TyAndLayout {
2127+
layout: tcx.intern_layout(layout),
2128+
ty: tag.value.to_ty(tcx),
2129+
}))
2130+
};
21522131

2153-
match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() {
2154-
ty::Slice(_) | ty::Str => tcx.types.usize,
2155-
ty::Dynamic(_, _) => {
2156-
tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.usize, 3))
2157-
/* FIXME: use actual fn pointers
2158-
Warning: naively computing the number of entries in the
2159-
vtable by counting the methods on the trait + methods on
2160-
all parent traits does not work, because some methods can
2161-
be not object safe and thus excluded from the vtable.
2162-
Increase this counter if you tried to implement this but
2163-
failed to do it without duplicating a lot of code from
2164-
other places in the compiler: 2
2165-
tcx.mk_tup(&[
2166-
tcx.mk_array(tcx.types.usize, 3),
2167-
tcx.mk_array(Option<fn()>),
2168-
])
2169-
*/
2132+
match *ty.kind() {
2133+
ty::Bool
2134+
| ty::Char
2135+
| ty::Int(_)
2136+
| ty::Uint(_)
2137+
| ty::Float(_)
2138+
| ty::FnPtr(_)
2139+
| ty::Never
2140+
| ty::FnDef(..)
2141+
| ty::GeneratorWitness(..)
2142+
| ty::Foreign(..)
2143+
| ty::Dynamic(..) => bug!("TyAndLayout::field_type({:?}): not applicable", this),
2144+
2145+
// Potentially-fat pointers.
2146+
ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
2147+
assert!(i < this.fields.count());
2148+
2149+
// Reuse the fat `*T` type as its own thin pointer data field.
2150+
// This provides information about, e.g., DST struct pointees
2151+
// (which may have no non-DST form), and will work as long
2152+
// as the `Abi` or `FieldsShape` is checked by users.
2153+
if i == 0 {
2154+
let nil = tcx.mk_unit();
2155+
let ptr_ty = if ty.is_unsafe_ptr() {
2156+
tcx.mk_mut_ptr(nil)
2157+
} else {
2158+
tcx.mk_mut_ref(tcx.lifetimes.re_static, nil)
2159+
};
2160+
return TyMaybeWithLayout::TyAndLayout(MaybeResult::from(
2161+
cx.layout_of(ptr_ty).to_result().map(|mut ptr_layout| {
2162+
ptr_layout.ty = ty;
2163+
ptr_layout
2164+
}),
2165+
));
21702166
}
2171-
_ => bug!("TyAndLayout::field_type({:?}): not applicable", this),
2172-
}
2173-
}
21742167

2175-
// Arrays and slices.
2176-
ty::Array(element, _) | ty::Slice(element) => element,
2177-
ty::Str => tcx.types.u8,
2178-
2179-
// Tuples, generators and closures.
2180-
ty::Closure(_, ref substs) => substs.as_closure().upvar_tys().nth(i).unwrap(),
2181-
2182-
ty::Generator(def_id, ref substs, _) => match this.variants {
2183-
Variants::Single { index } => substs
2184-
.as_generator()
2185-
.state_tys(def_id, tcx)
2186-
.nth(index.as_usize())
2187-
.unwrap()
2188-
.nth(i)
2189-
.unwrap(),
2190-
Variants::Multiple { ref tag, tag_field, .. } => {
2191-
if i == tag_field {
2192-
return tag_layout(tag);
2168+
match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() {
2169+
ty::Slice(_) | ty::Str => TyMaybeWithLayout::Ty(tcx.types.usize),
2170+
ty::Dynamic(_, _) => {
2171+
TyMaybeWithLayout::Ty(tcx.mk_imm_ref(
2172+
tcx.lifetimes.re_static,
2173+
tcx.mk_array(tcx.types.usize, 3),
2174+
))
2175+
/* FIXME: use actual fn pointers
2176+
Warning: naively computing the number of entries in the
2177+
vtable by counting the methods on the trait + methods on
2178+
all parent traits does not work, because some methods can
2179+
be not object safe and thus excluded from the vtable.
2180+
Increase this counter if you tried to implement this but
2181+
failed to do it without duplicating a lot of code from
2182+
other places in the compiler: 2
2183+
tcx.mk_tup(&[
2184+
tcx.mk_array(tcx.types.usize, 3),
2185+
tcx.mk_array(Option<fn()>),
2186+
])
2187+
*/
2188+
}
2189+
_ => bug!("TyAndLayout::field_type({:?}): not applicable", this),
21932190
}
2194-
substs.as_generator().prefix_tys().nth(i).unwrap()
21952191
}
2196-
},
21972192

2198-
ty::Tuple(tys) => tys[i].expect_ty(),
2193+
// Arrays and slices.
2194+
ty::Array(element, _) | ty::Slice(element) => TyMaybeWithLayout::Ty(element),
2195+
ty::Str => TyMaybeWithLayout::Ty(tcx.types.u8),
21992196

2200-
// ADTs.
2201-
ty::Adt(def, substs) => {
2202-
match this.variants {
2203-
Variants::Single { index } => def.variants[index].fields[i].ty(tcx, substs),
2197+
// Tuples, generators and closures.
2198+
ty::Closure(_, ref substs) => {
2199+
ty_and_layout_kind(this, cx, i, substs.as_closure().tupled_upvars_ty())
2200+
}
2201+
2202+
ty::Generator(def_id, ref substs, _) => match this.variants {
2203+
Variants::Single { index } => TyMaybeWithLayout::Ty(
2204+
substs
2205+
.as_generator()
2206+
.state_tys(def_id, tcx)
2207+
.nth(index.as_usize())
2208+
.unwrap()
2209+
.nth(i)
2210+
.unwrap(),
2211+
),
2212+
Variants::Multiple { ref tag, tag_field, .. } => {
2213+
if i == tag_field {
2214+
return TyMaybeWithLayout::TyAndLayout(tag_layout(tag));
2215+
}
2216+
TyMaybeWithLayout::Ty(substs.as_generator().prefix_tys().nth(i).unwrap())
2217+
}
2218+
},
2219+
2220+
ty::Tuple(tys) => TyMaybeWithLayout::Ty(tys[i].expect_ty()),
2221+
2222+
// ADTs.
2223+
ty::Adt(def, substs) => {
2224+
match this.variants {
2225+
Variants::Single { index } => {
2226+
TyMaybeWithLayout::Ty(def.variants[index].fields[i].ty(tcx, substs))
2227+
}
22042228

2205-
// Discriminant field for enums (where applicable).
2206-
Variants::Multiple { ref tag, .. } => {
2207-
assert_eq!(i, 0);
2208-
return tag_layout(tag);
2229+
// Discriminant field for enums (where applicable).
2230+
Variants::Multiple { ref tag, .. } => {
2231+
assert_eq!(i, 0);
2232+
return TyMaybeWithLayout::TyAndLayout(tag_layout(tag));
2233+
}
22092234
}
22102235
}
2236+
2237+
ty::Projection(_)
2238+
| ty::Bound(..)
2239+
| ty::Placeholder(..)
2240+
| ty::Opaque(..)
2241+
| ty::Param(_)
2242+
| ty::Infer(_)
2243+
| ty::Error(_) => bug!("TyAndLayout::field_type: unexpected type `{}`", this.ty),
22112244
}
2245+
}
22122246

2213-
ty::Projection(_)
2214-
| ty::Bound(..)
2215-
| ty::Placeholder(..)
2216-
| ty::Opaque(..)
2217-
| ty::Param(_)
2218-
| ty::Infer(_)
2219-
| ty::Error(_) => bug!("TyAndLayout::field_type: unexpected type `{}`", this.ty),
2247+
cx.layout_of(match ty_and_layout_kind(this, cx, i, this.ty) {
2248+
TyMaybeWithLayout::Ty(result) => result,
2249+
TyMaybeWithLayout::TyAndLayout(result) => return result,
22202250
})
22212251
}
22222252

compiler/rustc_trait_selection/src/opaque_types.rs

-10
Original file line numberDiff line numberDiff line change
@@ -722,11 +722,6 @@ where
722722
// Skip lifetime parameters of the enclosing item(s)
723723

724724
substs.as_closure().tupled_upvars_ty().visit_with(self);
725-
726-
for upvar_ty in substs.as_closure().upvar_tys() {
727-
upvar_ty.visit_with(self);
728-
}
729-
730725
substs.as_closure().sig_as_fn_ptr_ty().visit_with(self);
731726
}
732727

@@ -735,11 +730,6 @@ where
735730
// Also skip the witness type, because that has no free regions.
736731

737732
substs.as_generator().tupled_upvars_ty().visit_with(self);
738-
739-
for upvar_ty in substs.as_generator().upvar_tys() {
740-
upvar_ty.visit_with(self);
741-
}
742-
743733
substs.as_generator().return_ty().visit_with(self);
744734
substs.as_generator().yield_ty().visit_with(self);
745735
substs.as_generator().resume_ty().visit_with(self);

compiler/rustc_ty_utils/src/needs_drop.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -94,16 +94,12 @@ where
9494
_ if component.is_copy_modulo_regions(tcx.at(DUMMY_SP), self.param_env) => (),
9595

9696
ty::Closure(_, substs) => {
97-
for upvar_ty in substs.as_closure().upvar_tys() {
98-
queue_type(self, upvar_ty);
99-
}
97+
queue_type(self, substs.as_closure().tupled_upvars_ty());
10098
}
10199

102100
ty::Generator(def_id, substs, _) => {
103101
let substs = substs.as_generator();
104-
for upvar_ty in substs.upvar_tys() {
105-
queue_type(self, upvar_ty);
106-
}
102+
queue_type(self, substs.tupled_upvars_ty());
107103

108104
let witness = substs.witness();
109105
let interior_tys = match witness.kind() {

src/test/ui/issues/issue-78720.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
fn server() -> impl {
2+
//~^ ERROR at least one trait must be specified
3+
().map2(|| "")
4+
}
5+
6+
trait FilterBase2 {
7+
fn map2<F>(self, F) -> Map2<F> {}
8+
//~^ ERROR mismatched types
9+
//~^^ ERROR the size for values of type `Self` cannot be known at compilation time
10+
}
11+
12+
struct Map2<Segment2> {
13+
_func: F,
14+
//~^ ERROR cannot find type `F` in this scope
15+
}
16+
17+
impl<F> FilterBase2 for F {}
18+
19+
fn main() {}

src/test/ui/issues/issue-78720.stderr

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
error: at least one trait must be specified
2+
--> $DIR/issue-78720.rs:1:16
3+
|
4+
LL | fn server() -> impl {
5+
| ^^^^
6+
7+
error[E0412]: cannot find type `F` in this scope
8+
--> $DIR/issue-78720.rs:13:12
9+
|
10+
LL | _func: F,
11+
| ^
12+
|
13+
::: $SRC_DIR/core/src/ops/function.rs:LL:COL
14+
|
15+
LL | pub trait Fn<Args>: FnMut<Args> {
16+
| ------------------------------- similarly named trait `Fn` defined here
17+
|
18+
help: a trait with a similar name exists
19+
|
20+
LL | _func: Fn,
21+
| ^^
22+
help: you might be missing a type parameter
23+
|
24+
LL | struct Map2<Segment2, F> {
25+
| ^^^
26+
27+
error[E0308]: mismatched types
28+
--> $DIR/issue-78720.rs:7:36
29+
|
30+
LL | fn map2<F>(self, F) -> Map2<F> {}
31+
| ^^ expected struct `Map2`, found `()`
32+
|
33+
= note: expected struct `Map2<F>`
34+
found unit type `()`
35+
36+
error[E0277]: the size for values of type `Self` cannot be known at compilation time
37+
--> $DIR/issue-78720.rs:7:16
38+
|
39+
LL | fn map2<F>(self, F) -> Map2<F> {}
40+
| ^^^^ doesn't have a size known at compile-time
41+
|
42+
= help: unsized fn params are gated as an unstable feature
43+
help: consider further restricting `Self`
44+
|
45+
LL | fn map2<F>(self, F) -> Map2<F> where Self: Sized {}
46+
| ^^^^^^^^^^^^^^^^^
47+
help: function arguments must have a statically known size, borrowed types always have a known size
48+
|
49+
LL | fn map2<F>(&self, F) -> Map2<F> {}
50+
| ^
51+
52+
error: aborting due to 4 previous errors
53+
54+
Some errors have detailed explanations: E0277, E0308, E0412.
55+
For more information about an error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)