Skip to content

Commit dedf2ed

Browse files
committed
rustc_typeck: correctly compute Substs for Res::SelfCtor.
1 parent 374c63e commit dedf2ed

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
@@ -5300,52 +5300,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
53005300
Some(original_span.with_lo(original_span.hi() - BytePos(1)))
53015301
}
53025302

5303-
// Rewrite `SelfCtor` to `Ctor`
5304-
pub fn rewrite_self_ctor(
5305-
&self,
5306-
res: Res,
5307-
span: Span,
5308-
) -> Result<Res, ErrorReported> {
5309-
let tcx = self.tcx;
5310-
if let Res::SelfCtor(impl_def_id) = res {
5311-
let ty = self.impl_self_ty(span, impl_def_id).ty;
5312-
let adt_def = ty.ty_adt_def();
5313-
5314-
match adt_def {
5315-
Some(adt_def) if adt_def.has_ctor() => {
5316-
let variant = adt_def.non_enum_variant();
5317-
let ctor_def_id = variant.ctor_def_id.unwrap();
5318-
Ok(Res::Def(DefKind::Ctor(CtorOf::Struct, variant.ctor_kind), ctor_def_id))
5319-
}
5320-
_ => {
5321-
let mut err = tcx.sess.struct_span_err(span,
5322-
"the `Self` constructor can only be used with tuple or unit structs");
5323-
if let Some(adt_def) = adt_def {
5324-
match adt_def.adt_kind() {
5325-
AdtKind::Enum => {
5326-
err.help("did you mean to use one of the enum's variants?");
5327-
},
5328-
AdtKind::Struct |
5329-
AdtKind::Union => {
5330-
err.span_suggestion(
5331-
span,
5332-
"use curly brackets",
5333-
String::from("Self { /* fields */ }"),
5334-
Applicability::HasPlaceholders,
5335-
);
5336-
}
5337-
}
5338-
}
5339-
err.emit();
5340-
5341-
Err(ErrorReported)
5342-
}
5343-
}
5344-
} else {
5345-
Ok(res)
5346-
}
5347-
}
5348-
53495303
// Instantiates the given path, which must refer to an item with the given
53505304
// number of type parameters and type.
53515305
pub fn instantiate_value_path(&self,
@@ -5365,12 +5319,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
53655319

53665320
let tcx = self.tcx;
53675321

5368-
let res = match self.rewrite_self_ctor(res, span) {
5369-
Ok(res) => res,
5370-
Err(ErrorReported) => return (tcx.types.err, res),
5371-
};
53725322
let path_segs = match res {
5373-
Res::Local(_) => vec![],
5323+
Res::Local(_) | Res::SelfCtor(_) => vec![],
53745324
Res::Def(kind, def_id) =>
53755325
AstConv::def_ids_for_value_path_segments(self, segments, self_ty, kind, def_id),
53765326
_ => bug!("instantiate_value_path on {:?}", res),
@@ -5475,13 +5425,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
54755425
tcx.generics_of(*def_id).has_self
54765426
}).unwrap_or(false);
54775427

5428+
let (res, self_ctor_substs) = if let Res::SelfCtor(impl_def_id) = res {
5429+
let ty = self.impl_self_ty(span, impl_def_id).ty;
5430+
let adt_def = ty.ty_adt_def();
5431+
5432+
match ty.sty {
5433+
ty::Adt(adt_def, substs) if adt_def.has_ctor() => {
5434+
let variant = adt_def.non_enum_variant();
5435+
let ctor_def_id = variant.ctor_def_id.unwrap();
5436+
(
5437+
Res::Def(DefKind::Ctor(CtorOf::Struct, variant.ctor_kind), ctor_def_id),
5438+
Some(substs),
5439+
)
5440+
}
5441+
_ => {
5442+
let mut err = tcx.sess.struct_span_err(span,
5443+
"the `Self` constructor can only be used with tuple or unit structs");
5444+
if let Some(adt_def) = adt_def {
5445+
match adt_def.adt_kind() {
5446+
AdtKind::Enum => {
5447+
err.help("did you mean to use one of the enum's variants?");
5448+
},
5449+
AdtKind::Struct |
5450+
AdtKind::Union => {
5451+
err.span_suggestion(
5452+
span,
5453+
"use curly brackets",
5454+
String::from("Self { /* fields */ }"),
5455+
Applicability::HasPlaceholders,
5456+
);
5457+
}
5458+
}
5459+
}
5460+
err.emit();
5461+
5462+
return (tcx.types.err, res)
5463+
}
5464+
}
5465+
} else {
5466+
(res, None)
5467+
};
54785468
let def_id = res.def_id();
54795469

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

5484-
let substs = AstConv::create_substs_for_generic_args(
5474+
let substs = self_ctor_substs.unwrap_or_else(|| AstConv::create_substs_for_generic_args(
54855475
tcx,
54865476
def_id,
54875477
&[][..],
@@ -5551,7 +5541,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
55515541
}
55525542
}
55535543
},
5554-
);
5544+
));
55555545
assert!(!substs.has_escaping_bound_vars());
55565546
assert!(!ty.has_escaping_bound_vars());
55575547

src/test/run-pass/issues/issue-57924.rs 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)