Skip to content

Commit ccfb34f

Browse files
eddybMark-Simulacrum
authored andcommitted
rustc_typeck: correctly compute Substs for Res::SelfCtor.
1 parent b2f5f0f commit ccfb34f

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
@@ -5190,52 +5190,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
51905190
Some(original_span.with_lo(original_span.hi() - BytePos(1)))
51915191
}
51925192

5193-
// Rewrite `SelfCtor` to `Ctor`
5194-
pub fn rewrite_self_ctor(
5195-
&self,
5196-
res: Res,
5197-
span: Span,
5198-
) -> Result<Res, ErrorReported> {
5199-
let tcx = self.tcx;
5200-
if let Res::SelfCtor(impl_def_id) = res {
5201-
let ty = self.impl_self_ty(span, impl_def_id).ty;
5202-
let adt_def = ty.ty_adt_def();
5203-
5204-
match adt_def {
5205-
Some(adt_def) if adt_def.has_ctor() => {
5206-
let variant = adt_def.non_enum_variant();
5207-
let ctor_def_id = variant.ctor_def_id.unwrap();
5208-
Ok(Res::Def(DefKind::Ctor(CtorOf::Struct, variant.ctor_kind), ctor_def_id))
5209-
}
5210-
_ => {
5211-
let mut err = tcx.sess.struct_span_err(span,
5212-
"the `Self` constructor can only be used with tuple or unit structs");
5213-
if let Some(adt_def) = adt_def {
5214-
match adt_def.adt_kind() {
5215-
AdtKind::Enum => {
5216-
err.help("did you mean to use one of the enum's variants?");
5217-
},
5218-
AdtKind::Struct |
5219-
AdtKind::Union => {
5220-
err.span_suggestion(
5221-
span,
5222-
"use curly brackets",
5223-
String::from("Self { /* fields */ }"),
5224-
Applicability::HasPlaceholders,
5225-
);
5226-
}
5227-
}
5228-
}
5229-
err.emit();
5230-
5231-
Err(ErrorReported)
5232-
}
5233-
}
5234-
} else {
5235-
Ok(res)
5236-
}
5237-
}
5238-
52395193
// Instantiates the given path, which must refer to an item with the given
52405194
// number of type parameters and type.
52415195
pub fn instantiate_value_path(&self,
@@ -5255,12 +5209,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
52555209

52565210
let tcx = self.tcx;
52575211

5258-
let res = match self.rewrite_self_ctor(res, span) {
5259-
Ok(res) => res,
5260-
Err(ErrorReported) => return (tcx.types.err, res),
5261-
};
52625212
let path_segs = match res {
5263-
Res::Local(_) | Res::Upvar(..) => Vec::new(),
5213+
Res::Local(_) | Res::Upvar(..) | Res::SelfCtor(_) => vec![],
52645214
Res::Def(kind, def_id) =>
52655215
AstConv::def_ids_for_value_path_segments(self, segments, self_ty, kind, def_id),
52665216
_ => bug!("instantiate_value_path on {:?}", res),
@@ -5368,13 +5318,53 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
53685318
tcx.generics_of(*def_id).has_self
53695319
}).unwrap_or(false);
53705320

5321+
let (res, self_ctor_substs) = if let Res::SelfCtor(impl_def_id) = res {
5322+
let ty = self.impl_self_ty(span, impl_def_id).ty;
5323+
let adt_def = ty.ty_adt_def();
5324+
5325+
match ty.sty {
5326+
ty::Adt(adt_def, substs) if adt_def.has_ctor() => {
5327+
let variant = adt_def.non_enum_variant();
5328+
let ctor_def_id = variant.ctor_def_id.unwrap();
5329+
(
5330+
Res::Def(DefKind::Ctor(CtorOf::Struct, variant.ctor_kind), ctor_def_id),
5331+
Some(substs),
5332+
)
5333+
}
5334+
_ => {
5335+
let mut err = tcx.sess.struct_span_err(span,
5336+
"the `Self` constructor can only be used with tuple or unit structs");
5337+
if let Some(adt_def) = adt_def {
5338+
match adt_def.adt_kind() {
5339+
AdtKind::Enum => {
5340+
err.help("did you mean to use one of the enum's variants?");
5341+
},
5342+
AdtKind::Struct |
5343+
AdtKind::Union => {
5344+
err.span_suggestion(
5345+
span,
5346+
"use curly brackets",
5347+
String::from("Self { /* fields */ }"),
5348+
Applicability::HasPlaceholders,
5349+
);
5350+
}
5351+
}
5352+
}
5353+
err.emit();
5354+
5355+
return (tcx.types.err, res)
5356+
}
5357+
}
5358+
} else {
5359+
(res, None)
5360+
};
53715361
let def_id = res.def_id();
53725362

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

5377-
let substs = AstConv::create_substs_for_generic_args(
5367+
let substs = self_ctor_substs.unwrap_or_else(|| AstConv::create_substs_for_generic_args(
53785368
tcx,
53795369
def_id,
53805370
&[][..],
@@ -5444,7 +5434,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
54445434
}
54455435
}
54465436
},
5447-
);
5437+
));
54485438
assert!(!substs.has_escaping_bound_vars());
54495439
assert!(!ty.has_escaping_bound_vars());
54505440

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)