Skip to content

Commit 311025e

Browse files
author
Angelos Oikonomopoulos
committed
Fix generic argument lookup for Self
Rewrite the SelfCtor early and use the replacement Def when calculating the path_segs. Note that this also changes which def is seen by the code that computes user_self_ty and is_alias_variant_ctor; I don't see a immediate issue with that, but I'm not 100% clear on the implications. Fixes #57924
1 parent b58a006 commit 311025e

File tree

2 files changed

+69
-59
lines changed

2 files changed

+69
-59
lines changed

src/librustc_typeck/check/mod.rs

+60-59
Original file line numberDiff line numberDiff line change
@@ -5302,6 +5302,53 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
53025302
Some(original_span.with_lo(original_span.hi() - BytePos(1)))
53035303
}
53045304

5305+
// Rewrite `SelfCtor` to `StructCtor`
5306+
pub fn rewrite_self_ctor(&self, def: Def, span: Span) -> (Def, DefId, Ty<'tcx>) {
5307+
let tcx = self.tcx;
5308+
if let Def::SelfCtor(impl_def_id) = def {
5309+
let ty = self.impl_self_ty(span, impl_def_id).ty;
5310+
let adt_def = ty.ty_adt_def();
5311+
5312+
match adt_def {
5313+
Some(adt_def) if adt_def.has_ctor() => {
5314+
let variant = adt_def.non_enum_variant();
5315+
let def = Def::StructCtor(variant.did, variant.ctor_kind);
5316+
(def, variant.did, tcx.type_of(variant.did))
5317+
}
5318+
_ => {
5319+
let mut err = tcx.sess.struct_span_err(span,
5320+
"the `Self` constructor can only be used with tuple or unit structs");
5321+
if let Some(adt_def) = adt_def {
5322+
match adt_def.adt_kind() {
5323+
AdtKind::Enum => {
5324+
err.help("did you mean to use one of the enum's variants?");
5325+
},
5326+
AdtKind::Struct |
5327+
AdtKind::Union => {
5328+
err.span_suggestion(
5329+
span,
5330+
"use curly brackets",
5331+
String::from("Self { /* fields */ }"),
5332+
Applicability::HasPlaceholders,
5333+
);
5334+
}
5335+
}
5336+
}
5337+
err.emit();
5338+
5339+
(def, impl_def_id, tcx.types.err)
5340+
}
5341+
}
5342+
} else {
5343+
let def_id = def.def_id();
5344+
5345+
// The things we are substituting into the type should not contain
5346+
// escaping late-bound regions, and nor should the base type scheme.
5347+
let ty = tcx.type_of(def_id);
5348+
(def, def_id, ty)
5349+
}
5350+
}
5351+
53055352
// Instantiates the given path, which must refer to an item with the given
53065353
// number of type parameters and type.
53075354
pub fn instantiate_value_path(&self,
@@ -5321,6 +5368,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
53215368

53225369
let tcx = self.tcx;
53235370

5371+
match def {
5372+
Def::Local(nid) | Def::Upvar(nid, ..) => {
5373+
let hid = self.tcx.hir().node_to_hir_id(nid);
5374+
let ty = self.local_ty(span, hid).decl_ty;
5375+
let ty = self.normalize_associated_types_in(span, &ty);
5376+
self.write_ty(hir_id, ty);
5377+
return (ty, def);
5378+
}
5379+
_ => {}
5380+
}
5381+
5382+
let (def, def_id, ty) = self.rewrite_self_ctor(def, span);
53245383
let path_segs = AstConv::def_ids_for_path_segments(self, segments, self_ty, def);
53255384

53265385
let mut user_self_ty = None;
@@ -5382,17 +5441,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
53825441
user_self_ty = None;
53835442
}
53845443

5385-
match def {
5386-
Def::Local(nid) | Def::Upvar(nid, ..) => {
5387-
let hid = self.tcx.hir().node_to_hir_id(nid);
5388-
let ty = self.local_ty(span, hid).decl_ty;
5389-
let ty = self.normalize_associated_types_in(span, &ty);
5390-
self.write_ty(hir_id, ty);
5391-
return (ty, def);
5392-
}
5393-
_ => {}
5394-
}
5395-
53965444
// Now we have to compare the types that the user *actually*
53975445
// provided against the types that were *expected*. If the user
53985446
// did not provide any types, then we want to substitute inference
@@ -5425,53 +5473,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
54255473
tcx.generics_of(*def_id).has_self
54265474
}).unwrap_or(false);
54275475

5428-
let mut new_def = def;
5429-
let (def_id, ty) = match def {
5430-
Def::SelfCtor(impl_def_id) => {
5431-
let ty = self.impl_self_ty(span, impl_def_id).ty;
5432-
let adt_def = ty.ty_adt_def();
5433-
5434-
match adt_def {
5435-
Some(adt_def) if adt_def.has_ctor() => {
5436-
let variant = adt_def.non_enum_variant();
5437-
new_def = Def::StructCtor(variant.did, variant.ctor_kind);
5438-
(variant.did, tcx.type_of(variant.did))
5439-
}
5440-
_ => {
5441-
let mut err = tcx.sess.struct_span_err(span,
5442-
"the `Self` constructor can only be used with tuple or unit structs");
5443-
if let Some(adt_def) = adt_def {
5444-
match adt_def.adt_kind() {
5445-
AdtKind::Enum => {
5446-
err.help("did you mean to use one of the enum's variants?");
5447-
},
5448-
AdtKind::Struct |
5449-
AdtKind::Union => {
5450-
err.span_suggestion(
5451-
span,
5452-
"use curly brackets",
5453-
String::from("Self { /* fields */ }"),
5454-
Applicability::HasPlaceholders,
5455-
);
5456-
}
5457-
}
5458-
}
5459-
err.emit();
5460-
5461-
(impl_def_id, tcx.types.err)
5462-
}
5463-
}
5464-
}
5465-
_ => {
5466-
let def_id = def.def_id();
5467-
5468-
// The things we are substituting into the type should not contain
5469-
// escaping late-bound regions, and nor should the base type scheme.
5470-
let ty = tcx.type_of(def_id);
5471-
(def_id, ty)
5472-
}
5473-
};
5474-
54755476
let substs = AstConv::create_substs_for_generic_args(
54765477
tcx,
54775478
def_id,
@@ -5587,7 +5588,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
55875588
ty_substituted);
55885589
self.write_substs(hir_id, substs);
55895590

5590-
(ty_substituted, new_def)
5591+
(ty_substituted, def)
55915592
}
55925593

55935594
fn check_rustc_args_require_const(&self,
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
pub struct Gcm<E>(E);
2+
3+
impl<E> Gcm<E> {
4+
pub fn crash(e: E) -> Self {
5+
Self::<E>(e)
6+
}
7+
}
8+
9+
fn main() {}

0 commit comments

Comments
 (0)