Skip to content

Commit f755231

Browse files
authored
Rollup merge of rust-lang#61896 - eddyb:correct-self-ctor, r=petrochenkov
rustc_typeck: correctly compute `Substs` for `Res::SelfCtor`. Fixes rust-lang#61882. r? @petrochenkov cc @varkor
2 parents ebf9696 + dedf2ed commit f755231

File tree

7 files changed

+109
-53
lines changed

7 files changed

+109
-53
lines changed

src/librustc_typeck/check/mod.rs

+43-53
Original file line numberDiff line numberDiff line change
@@ -3957,52 +3957,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
39573957
Some(original_span.with_lo(original_span.hi() - BytePos(1)))
39583958
}
39593959

3960-
// Rewrite `SelfCtor` to `Ctor`
3961-
pub fn rewrite_self_ctor(
3962-
&self,
3963-
res: Res,
3964-
span: Span,
3965-
) -> Result<Res, ErrorReported> {
3966-
let tcx = self.tcx;
3967-
if let Res::SelfCtor(impl_def_id) = res {
3968-
let ty = self.impl_self_ty(span, impl_def_id).ty;
3969-
let adt_def = ty.ty_adt_def();
3970-
3971-
match adt_def {
3972-
Some(adt_def) if adt_def.has_ctor() => {
3973-
let variant = adt_def.non_enum_variant();
3974-
let ctor_def_id = variant.ctor_def_id.unwrap();
3975-
Ok(Res::Def(DefKind::Ctor(CtorOf::Struct, variant.ctor_kind), ctor_def_id))
3976-
}
3977-
_ => {
3978-
let mut err = tcx.sess.struct_span_err(span,
3979-
"the `Self` constructor can only be used with tuple or unit structs");
3980-
if let Some(adt_def) = adt_def {
3981-
match adt_def.adt_kind() {
3982-
AdtKind::Enum => {
3983-
err.help("did you mean to use one of the enum's variants?");
3984-
},
3985-
AdtKind::Struct |
3986-
AdtKind::Union => {
3987-
err.span_suggestion(
3988-
span,
3989-
"use curly brackets",
3990-
String::from("Self { /* fields */ }"),
3991-
Applicability::HasPlaceholders,
3992-
);
3993-
}
3994-
}
3995-
}
3996-
err.emit();
3997-
3998-
Err(ErrorReported)
3999-
}
4000-
}
4001-
} else {
4002-
Ok(res)
4003-
}
4004-
}
4005-
40063960
// Instantiates the given path, which must refer to an item with the given
40073961
// number of type parameters and type.
40083962
pub fn instantiate_value_path(&self,
@@ -4022,12 +3976,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
40223976

40233977
let tcx = self.tcx;
40243978

4025-
let res = match self.rewrite_self_ctor(res, span) {
4026-
Ok(res) => res,
4027-
Err(ErrorReported) => return (tcx.types.err, res),
4028-
};
40293979
let path_segs = match res {
4030-
Res::Local(_) => vec![],
3980+
Res::Local(_) | Res::SelfCtor(_) => vec![],
40313981
Res::Def(kind, def_id) =>
40323982
AstConv::def_ids_for_value_path_segments(self, segments, self_ty, kind, def_id),
40333983
_ => bug!("instantiate_value_path on {:?}", res),
@@ -4132,13 +4082,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
41324082
tcx.generics_of(*def_id).has_self
41334083
}).unwrap_or(false);
41344084

4085+
let (res, self_ctor_substs) = if let Res::SelfCtor(impl_def_id) = res {
4086+
let ty = self.impl_self_ty(span, impl_def_id).ty;
4087+
let adt_def = ty.ty_adt_def();
4088+
4089+
match ty.sty {
4090+
ty::Adt(adt_def, substs) if adt_def.has_ctor() => {
4091+
let variant = adt_def.non_enum_variant();
4092+
let ctor_def_id = variant.ctor_def_id.unwrap();
4093+
(
4094+
Res::Def(DefKind::Ctor(CtorOf::Struct, variant.ctor_kind), ctor_def_id),
4095+
Some(substs),
4096+
)
4097+
}
4098+
_ => {
4099+
let mut err = tcx.sess.struct_span_err(span,
4100+
"the `Self` constructor can only be used with tuple or unit structs");
4101+
if let Some(adt_def) = adt_def {
4102+
match adt_def.adt_kind() {
4103+
AdtKind::Enum => {
4104+
err.help("did you mean to use one of the enum's variants?");
4105+
},
4106+
AdtKind::Struct |
4107+
AdtKind::Union => {
4108+
err.span_suggestion(
4109+
span,
4110+
"use curly brackets",
4111+
String::from("Self { /* fields */ }"),
4112+
Applicability::HasPlaceholders,
4113+
);
4114+
}
4115+
}
4116+
}
4117+
err.emit();
4118+
4119+
return (tcx.types.err, res)
4120+
}
4121+
}
4122+
} else {
4123+
(res, None)
4124+
};
41354125
let def_id = res.def_id();
41364126

41374127
// The things we are substituting into the type should not contain
41384128
// escaping late-bound regions, and nor should the base type scheme.
41394129
let ty = tcx.type_of(def_id);
41404130

4141-
let substs = AstConv::create_substs_for_generic_args(
4131+
let substs = self_ctor_substs.unwrap_or_else(|| AstConv::create_substs_for_generic_args(
41424132
tcx,
41434133
def_id,
41444134
&[][..],
@@ -4208,7 +4198,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
42084198
}
42094199
}
42104200
},
4211-
);
4201+
));
42124202
assert!(!substs.has_escaping_bound_vars());
42134203
assert!(!ty.has_escaping_bound_vars());
42144204

src/test/run-pass/issues/issue-57924.rs renamed to src/test/ui/issues/issue-57924.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ pub struct Gcm<E>(E);
33
impl<E> Gcm<E> {
44
pub fn crash(e: E) -> Self {
55
Self::<E>(e)
6+
//~^ ERROR type arguments are not allowed for this type
67
}
78
}
89

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

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0109]: type arguments are not allowed for this type
2+
--> $DIR/issue-57924.rs:5:16
3+
|
4+
LL | Self::<E>(e)
5+
| ^ type argument not allowed
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0109`.

src/test/ui/issues/issue-61882-2.rs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
struct A<T>(T);
2+
3+
impl A<&'static u8> {
4+
fn f() {
5+
let x = 0;
6+
Self(&x);
7+
//~^ ERROR `x` does not live long enough
8+
}
9+
}
10+
11+
fn main() {}
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0597]: `x` does not live long enough
2+
--> $DIR/issue-61882-2.rs:6:14
3+
|
4+
LL | Self(&x);
5+
| ^^
6+
| |
7+
| borrowed value does not live long enough
8+
| requires that `x` is borrowed for `'static`
9+
LL |
10+
LL | }
11+
| - `x` dropped here while still borrowed
12+
13+
error: aborting due to previous error
14+
15+
For more information about this error, try `rustc --explain E0597`.

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

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
struct A<T>(T);
2+
3+
impl A<bool> {
4+
const B: A<u8> = Self(0);
5+
//~^ ERROR mismatched types
6+
//~| ERROR mismatched types
7+
}
8+
9+
fn main() {}

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

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-61882.rs:4:27
3+
|
4+
LL | const B: A<u8> = Self(0);
5+
| ^ expected bool, found integer
6+
|
7+
= note: expected type `bool`
8+
found type `{integer}`
9+
10+
error[E0308]: mismatched types
11+
--> $DIR/issue-61882.rs:4:22
12+
|
13+
LL | const B: A<u8> = Self(0);
14+
| ^^^^^^^ expected u8, found bool
15+
|
16+
= note: expected type `A<u8>`
17+
found type `A<bool>`
18+
19+
error: aborting due to 2 previous errors
20+
21+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)