Skip to content

Commit ae5856f

Browse files
authored
Rollup merge of rust-lang#59025 - aoikonomopoulos:issue-57924, r=varkor
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 rust-lang#57924 r? @eddyb
2 parents ba9323f + 311025e commit ae5856f

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
@@ -5288,6 +5288,53 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
52885288
Some(original_span.with_lo(original_span.hi() - BytePos(1)))
52895289
}
52905290

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

53085355
let tcx = self.tcx;
53095356

5357+
match def {
5358+
Def::Local(nid) | Def::Upvar(nid, ..) => {
5359+
let hid = self.tcx.hir().node_to_hir_id(nid);
5360+
let ty = self.local_ty(span, hid).decl_ty;
5361+
let ty = self.normalize_associated_types_in(span, &ty);
5362+
self.write_ty(hir_id, ty);
5363+
return (ty, def);
5364+
}
5365+
_ => {}
5366+
}
5367+
5368+
let (def, def_id, ty) = self.rewrite_self_ctor(def, span);
53105369
let path_segs = AstConv::def_ids_for_path_segments(self, segments, self_ty, def);
53115370

53125371
let mut user_self_ty = None;
@@ -5368,17 +5427,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
53685427
user_self_ty = None;
53695428
}
53705429

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-
53825430
// Now we have to compare the types that the user *actually*
53835431
// provided against the types that were *expected*. If the user
53845432
// did not provide any types, then we want to substitute inference
@@ -5411,53 +5459,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
54115459
tcx.generics_of(*def_id).has_self
54125460
}).unwrap_or(false);
54135461

5414-
let mut new_def = def;
5415-
let (def_id, ty) = match def {
5416-
Def::SelfCtor(impl_def_id) => {
5417-
let ty = self.impl_self_ty(span, impl_def_id).ty;
5418-
let adt_def = ty.ty_adt_def();
5419-
5420-
match adt_def {
5421-
Some(adt_def) if adt_def.has_ctor() => {
5422-
let variant = adt_def.non_enum_variant();
5423-
new_def = Def::StructCtor(variant.did, variant.ctor_kind);
5424-
(variant.did, tcx.type_of(variant.did))
5425-
}
5426-
_ => {
5427-
let mut err = tcx.sess.struct_span_err(span,
5428-
"the `Self` constructor can only be used with tuple or unit structs");
5429-
if let Some(adt_def) = adt_def {
5430-
match adt_def.adt_kind() {
5431-
AdtKind::Enum => {
5432-
err.help("did you mean to use one of the enum's variants?");
5433-
},
5434-
AdtKind::Struct |
5435-
AdtKind::Union => {
5436-
err.span_suggestion(
5437-
span,
5438-
"use curly brackets",
5439-
String::from("Self { /* fields */ }"),
5440-
Applicability::HasPlaceholders,
5441-
);
5442-
}
5443-
}
5444-
}
5445-
err.emit();
5446-
5447-
(impl_def_id, tcx.types.err)
5448-
}
5449-
}
5450-
}
5451-
_ => {
5452-
let def_id = def.def_id();
5453-
5454-
// The things we are substituting into the type should not contain
5455-
// escaping late-bound regions, and nor should the base type scheme.
5456-
let ty = tcx.type_of(def_id);
5457-
(def_id, ty)
5458-
}
5459-
};
5460-
54615462
let substs = AstConv::create_substs_for_generic_args(
54625463
tcx,
54635464
def_id,
@@ -5573,7 +5574,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
55735574
ty_substituted);
55745575
self.write_substs(hir_id, substs);
55755576

5576-
(ty_substituted, new_def)
5577+
(ty_substituted, def)
55775578
}
55785579

55795580
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)